Brute Force, Simulation, Prefix Sum, and Difference Array Techniques

Overview of Core Algorithmic Strategies

1. Brute Force Anumeration

Brute force involves systematicallly checking all possible candidates to find valid solutions. While straightforward, its time complexity is often O(n²) or higher, so input constraints must be carefully considered.

Example Problem: Counting Valid Triangles
Given N sticks with lengths D₁, D₂, ..., Dₙ, count the number of distinct triplets that can form a triangle (i.e., satisfy the triangle inequality).

Optimized Approach:
Sort the array first. For each pair (i, j) where i < j, only consider k > j. Early termination is possible: if D[i] + D[j] ≤ D[j+1], no larger k will work due to sorting.

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    int n;
    cin >> n;
    vector<int> sticks(n);
    for (int i = 0; i < n; ++i) cin >> sticks[i];
    sort(sticks.begin(), sticks.end());

    long long count = 0;
    for (int i = 0; i < n; ++i) {
        for (int j = i + 1; j < n; ++j) {
            if (sticks[i] + sticks[j] <= sticks[j + 1]) continue;
            for (int k = j + 1; k < n; ++k) {
                if (sticks[i] + sticks[j] > sticks[k]) {
                    count++;
                } else {
                    break; // Further k won't satisfy due to sorted order
                }
            }
        }
    }
    cout << count << endl;
    return 0;
}

2. Simulation

Simulation requires implementing the exact logic described in the problem statement. These problems often involve managing states and events over time.

Example Problem: Public Transport Fare Calculation
After taking a subway (cost p), a user receives a 45-minute voucher usable on buses with fare ≤ p. Vouchers are used in FIFO order. Compute total expenditure given a chronological list of rides.

Key Insight:
Maintain a queue of active vouchers. For each bus ride, scan from the earliest voucher onward to find the first valid one. Expired vouchers can be skipped using a sliding window pointer.

#include <bits/stdc++.h>
using namespace std;

struct Voucher {
    int price;
    int timestamp;
    bool used;
};

int main() {
    ios::sync_with_stdio(false);
    int n;
    cin >> n;
    vector<Voucher> vouchers;
    long long totalCost = 0;
    int earliestValid = 0;

    for (int i = 0; i < n; ++i) {
        int type, price, time;
        cin >> type >> price >> time;

        if (type == 0) { // Subway
            totalCost += price;
            vouchers.push_back({price, time, false});
        } else { // Bus
            bool usedVoucher = false;
            for (int j = earliestValid; j < vouchers.size(); ++j) {
                if (time - vouchers[j].timestamp > 45) {
                    earliestValid = j + 1;
                    continue;
                }
                if (!vouchers[j].used && vouchers[j].price >= price) {
                    vouchers[j].used = true;
                    usedVoucher = true;
                    break;
                }
            }
            if (!usedVoucher) totalCost += price;
        }
    }
    cout << totalCost << endl;
    return 0;
}

3. Prefix Sum and Difference Array

Prefix Sum: Precompute cumulative sums to answer range sum queries in O(1).
Difference Array: Apply range updates (add/subtract a value over an interval) in O(1), then reconstruct the final array via prefix sum.

These techniques are inverses: applying a difference array followed by a prefix sum recovers the original transformation.

Tags: C++ brute-force simulation prefix-sum difference-array

Posted on Sun, 26 Jul 2026 16:32:37 +0000 by busnut