Competitive Programming Solutions: Algorithmic Strategies

Problem 1: Frequency Balance Optimization

Brute force enumeration approach.

We iterate through all possible height levels from 1 to n, calculating the maximum achievable sum by counting elements that can meet the height constraint at each level.

View solution code``` #include #include #include

using namespace std;

void solve() { int size; cin >> size;

vector<int> frequency(size + 1, 0);
for (int i = 0; i < size; i++) {
    int value;
    cin >> value;
    frequency[value]++;
}

int bestResult = 0;
for (int level = 1; level <= size; level++) {
    int currentSum = 0;
    for (int num = 1; num <= size; num++) {
        if (frequency[num] >= level) {
            currentSum += level;
        }
    }
    bestResult = max(bestResult, currentSum);
}

cout << bestResult << "\n";

}

int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr);

int testCases;
cin >> testCases;
while (testCases--) {
    solve();
}

return 0;

}


Problem 2: Set Union Strategy
====================

Logical reasoning required.

First, we tally the occurrence count of each element across all sets. Elements appearing only once indicate that their containing sets are essential. Let essentialCount represent the number of mandatory sets. If the total number of sets exceeds essentialCount + 1, we can construct all four possible combinations (00, 01, 10, 11).

View solution code```
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

void solve() {
    int numSets, numElements;
    cin >> numSets >> numElements;
    
    vector<vector<int>> sets(numSets);
    vector<int> elementCount(numElements + 1, 0);
    
    for (int i = 0; i < numSets; i++) {
        int setSize;
        cin >> setSize;
        sets[i].resize(setSize);
        for (int j = 0; j < setSize; j++) {
            int element;
            cin >> element;
            sets[i][j] = element;
            elementCount[element]++;
        }
    }
    
    if (find(elementCount.begin() + 1, elementCount.end(), 0) != elementCount.end()) {
        cout << "NO\n";
        return;
    }
    
    int essentialCount = 0;
    for (const auto& currentSet : sets) {
        bool hasUnique = false;
        for (int element : currentSet) {
            if (elementCount[element] == 1) {
                hasUnique = true;
                break;
            }
        }
        if (hasUnique) essentialCount++;
    }
    
    if (numSets > essentialCount + 1) {
        cout << "YES\n";
    } else {
        cout << "NO\n";
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int testCases;
    cin >> testCases;
    while (testCases--) {
        solve();
    }
    
    return 0;
}

Problem 3: Binary Search Pattern Construction

Array construction technique.

Analysis reveals that for positions marked with '1', no larger elements should appear to their left, and no smaller elements should appear to their right. Therefore, position i must contain i first. Between two consecutive '1's, we can create a shifted sequence like n, 1, 2, ..., n-1. Finally, we verify that no '0' position cnotains its own index.

View solution code``` #include #include #include

using namespace std;

void solve() { int length; cin >> length;

string pattern;
cin >> pattern;

pattern = " " + pattern;
vector<int> result(length + 1);
int lastPosition = 1;

for (int i = 1; i <= length; i++) {
    if (pattern[i] == '1') {
        result[i] = i;
        if (lastPosition < i) {
            result[lastPosition] = i - 1;
            for (int j = lastPosition + 1; j < i; j++) {
                result[j] = j - 1;
            }
        }
        lastPosition = i + 1;
    }
}

if (lastPosition <= length) {
    result[lastPosition] = length;
    for (int i = lastPosition + 1; i <= length; i++) {
        result[i] = i - 1;
    }
}

for (int i = 1; i <= length; i++) {
    if (pattern[i] == '0' && result[i] == i) {
        cout << "NO\n";
        return;
    }
}

cout << "YES\n";
for (int i = 1; i <= length; i++) {
    cout << result[i] << (i == length ? "\n" : " ");
}

}

int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr);

int testCases;
cin >> testCases;
while (testCases--) {
    solve();
}

return 0;

}


Problem 4: Maximum OR Sum (Easy Variant)
==============================

Bit manipulation and strategic pairing.

Since the range includes all numbers from 0 to r, for any number, there exists a corresponding number where bits after the most significant bit are inverted. For example, 10100 pairs with 01011.

The solution is to set all bits after the most significant bit to 1, then XOR this with the original number.

View solution code```
#include <iostream>
#include <vector>

using namespace std;

void solve() {
    int leftBound, rightBound;
    cin >> leftBound >> rightBound;
    
    vector<int> pairing(rightBound + 1, -1);
    long long total = 0;
    
    for (int current = rightBound; current >= leftBound; current--) {
        if (pairing[current] != -1) {
            total += pairing[current] | current;
            continue;
        }
        
        int mask = 0;
        for (int bit = 31; bit >= 0; bit--) {
            if ((current >> bit) & 1) {
                mask = (1 << (bit + 1)) - 1;
                break;
            }
        }
        
        int partner = mask ^ current;
        pairing[current] = partner;
        pairing[partner] = current;
        total += partner | current;
    }
    
    cout << total << "\n";
    for (int i = leftBound; i <= rightBound; i++) {
        cout << pairing[i] << (i == rightBound ? "\n" : " ");
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int testCases;
    cin >> testCases;
    while (testCases--) {
        solve();
    }
    
    return 0;
}

Problem 5: Maximum OR Sum (Hard Variant)

Bit manipulation with recursive pairing.

The solution involves processing bits from most significant to least significant. At each bit position, we identify the boundary between 0s and 1s, then symmetrically pair elements across this boundary.

View solution code``` #include #include #include

using namespace std;

void solve() { int leftBound, rightBound; cin >> leftBound >> rightBound;

int size = rightBound - leftBound + 1;
vector<int> numbers(size);
for (int i = 0; i < size; i++) {
    numbers[i] = leftBound + i;
}

int leftIdx = 0, rightIdx = size;
for (int bit = 30; bit >= 0; bit--) {
    int splitPoint = leftIdx;
    while (splitPoint < rightIdx && ((numbers[splitPoint] >> bit) & 1) == 0) {
        splitPoint++;
    }
    
    if (splitPoint - leftIdx < rightIdx - splitPoint) {
        int mirrorPoint = 2 * splitPoint - leftIdx;
        reverse(numbers.begin() + leftIdx, numbers.begin() + mirrorPoint);
        leftIdx = mirrorPoint;
    } else {
        int mirrorPoint = 2 * splitPoint - rightIdx;
        reverse(numbers.begin() + mirrorPoint, numbers.begin() + rightIdx);
        rightIdx = mirrorPoint;
    }
}

long long totalSum = 0;
for (int i = 0; i < size; i++) {
    totalSum += numbers[i] | (leftBound + i);
}

cout << totalSum << "\n";
for (int i = 0; i < size; i++) {
    cout << numbers[i] << (i + 1 == size ? "\n" : " ");
}

}

int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr);

int testCases;
cin >> testCases;
while (testCases--) {
    solve();
}

return 0;

}


Problem 6: MEX Subarray Analysis
======================

Segment tree data structure application.

For an array 'a' and an integer 'x' not present in 'a', define g(a, x) as the count of elements greater than x. Since g(a, x) ≤ g(a, mex(a)), the maximum occurs when x = mex(a).

For a fixed right endpoint r, we enumerate x to maximize g(a[l..r], x) while ensuring the subarray doesn't contain x. The optimal l is lst_x + 1, where lst_x is the last occurrence of x.

The solution requires tracking g(a, x) efficiently using a segment tree, handling range updates when new elements are added.

View solution code```
#include <iostream>
#include <vector>

using namespace std;

struct SegmentNode {
    int left, right;
    long long lazyAdd, maxValue;
};

class SegmentTree {
private:
    int treeSize;
    vector<SegmentNode> tree;
    
    void applyLazy(SegmentNode& parent, SegmentNode& child) {
        child.maxValue += parent.lazyAdd;
        child.lazyAdd += parent.lazyAdd;
    }
    
    void pushDown(int node) {
        if (tree[node].lazyAdd != 0) {
            applyLazy(tree[node], tree[node * 2]);
            applyLazy(tree[node], tree[node * 2 + 1]);
            tree[node].lazyAdd = 0;
        }
    }
    
    void pushUp(int node) {
        tree[node].maxValue = max(tree[node * 2].maxValue, tree[node * 2 + 1].maxValue);
    }
    
    void build(int node, int left, int right) {
        tree[node].left = left;
        tree[node].right = right;
        tree[node].lazyAdd = 0;
        tree[node].maxValue = 0;
        
        if (left == right) return;
        
        int mid = (left + right) / 2;
        build(node * 2, left, mid);
        build(node * 2 + 1, mid + 1, right);
    }
    
    void updateRange(int node, int left, int right, long long value) {
        if (tree[node].left >= left && tree[node].right <= right) {
            tree[node].lazyAdd += value;
            tree[node].maxValue += value;
            return;
        }
        
        pushDown(node);
        int mid = (tree[node].left + tree[node].right) / 2;
        
        if (left <= mid) {
            updateRange(node * 2, left, right, value);
        }
        if (right > mid) {
            updateRange(node * 2 + 1, left, right, value);
        }
        
        pushUp(node);
    }
    
    void updatePoint(int node, int position, long long value) {
        if (tree[node].left == tree[node].right) {
            tree[node].maxValue = value;
            return;
        }
        
        pushDown(node);
        int mid = (tree[node].left + tree[node].right) / 2;
        
        if (position <= mid) {
            updatePoint(node * 2, position, value);
        } else {
            updatePoint(node * 2 + 1, position, value);
        }
        
        pushUp(node);
    }
    
public:
    SegmentTree(int size) : treeSize(size) {
        tree.resize(4 * size + 10);
        build(1, 1, size);
    }
    
    void rangeUpdate(int left, int right, long long value) {
        updateRange(1, left, right, value);
    }
    
    void pointUpdate(int position, long long value) {
        updatePoint(1, position, value);
    }
    
    long long queryMaximum() {
        return tree[1].maxValue;
    }
};

void solve() {
    int arraySize;
    cin >> arraySize;
    
    vector<int> inputArray(arraySize + 2);
    SegmentTree segmentTree(arraySize + 2);
    
    for (int i = 1; i <= arraySize; i++) {
        cin >> inputArray[i];
        inputArray[i]++; // Offset to handle x = 0 case
    }
    
    for (int i = 1; i <= arraySize; i++) {
        segmentTree.rangeUpdate(1, inputArray[i], 1);
        segmentTree.pointUpdate(inputArray[i], 0);
        cout << segmentTree.queryMaximum() << (i == arraySize ? "\n" : " ");
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int testCases;
    cin >> testCases;
    while (testCases--) {
        solve();
    }
    
    return 0;
}

Tags: Codeforces Competitive Programming segment tree Bit Manipulation Array Algorithms

Posted on Wed, 08 Jul 2026 16:42:36 +0000 by mottwsc