Competitive Programming: Algorithmic Solutions for Mathematical and Tree Problems

Counting Valid Mountain Sequences

To solve the mountain sequence counting problem, we need to determine the number of permutations that satisfy the mountain property. This can be efficiently computed using combinatorial mathematics by recognizing patterns in the sorted sequence.

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

typedef long long ll;
const int MOD = 998244353;

int main() {
    int test_cases;
    cin >> test_cases;
    
    while (test_cases--) {
        int n;
        cin >> n;
        vector<int> sequence(n);
        
        for (int i = 0; i < n; i++) {
            cin >> sequence[i];
        }
        
        sort(sequence.begin(), sequence.end());
        
        int unique_end = n - 1;
        while (unique_end >= 0 && sequence[unique_end] == sequence[n-1]) {
            unique_end--;
        }
        
        ll result = 1;
        int current_start = 0;
        int current_count = 0;
        
        for (int i = 0; i <= unique_end; i++) {
            if (sequence[current_start] != sequence[i]) {
                result = (current_count + 1) * result % MOD;
                current_start = i;
                current_count = 1;
            } else {
                current_count++;
            }
        }
        
        result = (current_count + 1) * result % MOD;
        cout << result << endl;
    }
    
    return 0;
}

Constrained Binary Search Simulation

This problem requires simulating a binary search process with a limited number of operations. The solution involves carefully implementing the binary search algorithm while respecting the operation constraints.

#include <iostream>
using namespace std;

int main() {
    int test_cases;
    cin >> test_cases;
    
    while (test_cases--) {
        int left_bound, right_bound, max_operations;
        cin >> left_bound >> right_bound >> max_operations;
        
        int midpoint;
        while (max_operations > 0 && left_bound <= right_bound) {
            midpoint = (left_bound + right_bound) / 2;
            
            if (right_bound - midpoint > midpoint - left_bound) {
                left_bound = midpoint + 1;
            } else {
                right_bound = midpoint - 1;
            }
            
            max_operations--;
        }
        
        if (max_operations > 0) {
            cout << -1 << endl;
        } else {
            cout << midpoint << endl;
        }
    }
    
    return 0;
}

Computing Maximum Slope in a Sequence

The maximum slope problem can be simplified by recognizing that the maximum absolute slope between any two points in a sequence occurs between adjacent elements. This insight allows us to reduce the problem to checking consecutive differences.

#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;

typedef long double ld;

int main() {
    int sequence_size, query_count;
    cin >> sequence_size >> query_count;
    
    vector<int> values(sequence_size);
    for (int i = 0; i < sequence_size; i++) {
        cin >> values[i];
    }
    
    vector<int> differences(sequence_size-1);
    for (int i = 0; i < sequence_size-1; i++) {
        differences[i] = values[i+1] - values[i];
    }
    
    ld max_slope = 0;
    for (int i = 0; i < sequence_size-1; i++) {
        max_slope = max(max_slope, (ld)abs(differences[i]));
    }
    
    cout << fixed << max_slope << endl;
    
    while (query_count--) {
        int left, right, delta;
        cin >> left >> right >> delta;
        
        if (left > 1) {
            int idx = left - 2;
            differences[idx] += delta;
            max_slope = max(max_slope, (ld)abs(differences[idx]));
        }
        
        if (right < sequence_size) {
            int idx = right - 1;
            differences[idx] -= delta;
            max_slope = max(max_slope, (ld)abs(differences[idx]));
        }
        
        cout << fixed << max_slope << endl;
    }
    
    return 0;
}

Tree Ancestry Query Processing

This problem involves answering queries about node relationships in a tree structure. The solution uses Depth-First Search to assign discovery times and processes queries efficiently using a Fenwick Tree (Binary Indexed Tree).

#include <iostream>
#include <vector>
using namespace std;

class TreeQueryProcessor {
private:
    vector<vector<int>> adjacency;
    vector<int> discovery_time;
    vector<int> subtree_size;
    vector<int> fenwick;
    int node_count, marked_count, query_count;
    
    void dfs_traversal(int node, int parent) {
        discovery_time[node] = discovery_time.size();
        discovery_time.push_back(node);
        subtree_size[node] = 1;
        
        for (int neighbor : adjacency[node]) {
            if (neighbor != parent) {
                dfs_traversal(neighbor, node);
                subtree_size[node] += subtree_size[neighbor];
            }
        }
    }
    
    void update_fenwick(int index, int delta) {
        for (int i = index; i <= node_count; i += (i & -i)) {
            fenwick[i] += delta;
        }
    }
    
    int query_fenwick(int index) {
        int sum = 0;
        for (int i = index; i > 0; i -= (i & -i)) {
            sum += fenwick[i];
        }
        return sum;
    }
    
    void process_node(int node, int parent, vector<int>& marked_nodes, vector<pair<int, int>>& queries) {
        for (int marked : marked_nodes) {
            update_fenwick(discovery_time[marked], 1);
        }
        
        for (auto& query : queries) {
            int query_node = query.first;
            int query_idx = query.second;
            int start = discovery_time[query_node];
            int end = start + subtree_size[query_node] - 1;
            
            int result = query_fenwick(end) - query_fenwick(start - 1);
            // Store result for query_idx
        }
        
        for (int neighbor : adjacency[node]) {
            if (neighbor != parent) {
                process_node(neighbor, node, marked_nodes, queries);
            }
        }
        
        for (int marked : marked_nodes) {
            update_fenwick(discovery_time[marked], -1);
        }
    }

public:
    TreeQueryProcessor(int nodes, int marked, int queries) 
        : node_count(nodes), marked_count(marked), query_count(queries) {
        adjacency.resize(node_count + 1);
        discovery_time.reserve(node_count + 1);
        subtree_size.resize(node_count + 1, 0);
        fenwick.resize(node_count + 1, 0);
    }
    
    void add_edge(int u, int v) {
        adjacency[u].push_back(v);
        adjacency[v].push_back(u);
    }
    
    void process_queries(vector<int>& marked_nodes, vector<pair<int, int>>& queries) {
        dfs_traversal(1, 0);
        process_node(1, 0, marked_nodes, queries);
    }
};

int main() {
    int n, m, q;
    cin >> n >> m >> q;
    
    TreeQueryProcessor processor(n, m, q);
    
    for (int i = 0; i < n - 1; i++) {
        int u, v;
        cin >> u >> v;
        processor.add_edge(u, v);
    }
    
    vector<int> marked_nodes(m);
    for (int i = 0; i < m; i++) {
        cin >> marked_nodes[i];
    }
    
    vector<pair<int, int>> queries(q);
    for (int i = 0; i < q; i++) {
        int u, v;
        cin >> u >> v;
        queries[i] = {u, v};
    }
    
    processor.process_queries(marked_nodes, queries);
    
    // Output results for each query
    
    return 0;
}

Additional Contest Problems

The competition also featured problems related to high contrast patterns and jewel maximizing magic, which require advanced algorithmic techniques and efficient data structures for optimal solutions.

Tags: Competitive Programming algorithms combinatorics Binary Search tree traversal

Posted on Wed, 14 Oct 2026 16:38:16 +0000 by jonorr1