GCD Optimization in Array Processing
When working with arrays, selecting the minimum element first often leads to optimal solutions for GCD-based problems. Consider an array where each element's GCD with previous selections contributes to the total sum. The optimal approach involves:
- Sorting the array and selecting the smallest element first
- Calculating GCDs with subsequent elements while maintaining the running GCD
- Accumulating the sum of these GCD values
int computeOptimalGCDSum(vector<int>& arr) {
sort(arr.begin(), arr.end());
int current_gcd = 0, total = 0;
vector<bool> processed(arr.size(), false);
for (int i = 0; i < arr.size(); ++i) {
int min_gcd = INT_MAX, min_idx = -1;
for (int j = 0; j < arr.size(); ++j) {
if (!processed[j]) {
int temp_gcd = gcd(current_gcd, arr[j]);
if (temp_gcd < min_gcd) {
min_gcd = temp_gcd;
min_idx = j;
}
}
}
if (min_gcd == current_gcd) {
total += (arr.size() - i) * current_gcd;
break;
}
processed[min_idx] = true;
current_gcd = min_gcd;
total += current_gcd;
}
return total;
}
Median Calculation with Binary Search
For finding medians in segmented arrays, a binary search approach proves efficient:
- Preprocess the array with prefix sums
- For each query, binary search the median value
- Verify the median by checking segment counts
bool verifyMedian(const vector<int>& prefix, int x, int m, int n) {
int count = 0;
for (int k = 0; k * x <= n; ++k) {
int lower = k * x;
int upper = min(k * x + m, n);
count += (k == 0) ? prefix[upper] : prefix[upper] - prefix[lower - 1];
}
return count >= (n + 1) / 2;
}
int findMedian(const vector<int>& arr, int x) {
vector<int> prefix(arr.size() + 1, 0);
for (int i = 1; i <= arr.size(); ++i) {
prefix[i] = prefix[i - 1] + (arr[i - 1] <= i);
}
int left = 0, right = x;
while (left < right) {
int mid = left + (right - left) / 2;
if (verifyMedian(prefix, x, mid, arr.size())) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
Tree DP for Maximum Value Selection
In tree structures, dynamic programming helps maximize selected values while considering constraints:
struct TreeNode {
int value;
int cost;
vector<TreeNode*> children;
};
pair<int, int> treeMaxSelection(TreeNode* node) {
if (!node) return {0, 0};
int select = node->value;
int not_select = 0;
for (auto child : node->children) {
auto [child_select, child_not_select] = treeMaxSelection(child);
not_select += max(child_select, child_not_select);
select += max(child_select - 2 * node->cost, child_not_select);
}
return {select, not_select};
}