Submission #59721

#TimeUsernameProblemLanguageResultExecution timeMemory
59721model_codeElection (BOI18_election)C++17
82 / 100
3052 ms27468 KiB
// Andrei-Costin Constantinescu
// O(NlogN)
#include <bits/stdc++.h>

using namespace std;

const int NMAX = 500000 + 5;
int N, v[NMAX];

struct Node {
    int l, r;
    int sum, minSuf;
    Node(): l(-1), r(-1), sum(-1), minSuf(-1) {}
    Node(int _l, int _r, int _sum, int _minSuf): l(_l), r(_r), sum(_sum), minSuf(_minSuf) {}

    static Node singleNode(const int l, const int r, const int val) {
        return Node(l, r, val, min(val, 0));
    }
    friend Node operator+(const Node &arg0, const Node &arg1) {
        if (arg0.r == -1)
            return arg1;
        return Node(arg0.l, arg1.r, arg0.sum + arg1.sum, min(arg0.minSuf + arg1.sum, arg1.minSuf));
    }
};

const int SQRT = 500;
Node buckets[NMAX / SQRT + 5];

inline int bucketLeft(int bucket) { return (bucket - 1) * SQRT + 1; }
inline int bucketRight(int bucket) { return min(N, bucket * SQRT); }
inline int whichBucket(int pos) { return (pos - 1) / SQRT + 1; }

void buildBucket(int bucket) {
    const int l = bucketLeft(bucket), r = bucketRight(bucket);
    buckets[bucket] = Node();
    for (int i = l; i <= r; ++ i)
        buckets[bucket] = buckets[bucket] + Node :: singleNode(i, i, v[i]);
}

void updatePos(int where, int addent) {
    v[where] += addent;
    buildBucket(whichBucket(where));
}

Node query(int l, int r) {
    Node ans;
    while (l <= r) {
        const int b = whichBucket(l);
        if (l == bucketLeft(b) && l + SQRT - 1 <= r) {
            ans = ans + buckets[b];
            l += SQRT;
        }
        else {
            ans = ans + Node :: singleNode(l, l, v[l]);
            l += 1;
        }
    }
    return ans;
}

struct Query {
    int r, pos;
    Query(int _r = 0, int _pos = 0):
        r(_r), pos(_pos) {}
};
vector <Query> queries[NMAX];
int answers[NMAX];

int main() {
    cin >> N;
    assert(1 <= N && N <= 500000);

    string votes;
    cin >> votes;
    assert(static_cast <int>(votes.size()) == N);

    for (int i = 1; i <= N; ++ i) {
        assert(votes[i - 1] == 'C' || votes[i - 1] == 'T');
        v[i] = votes[i - 1] == 'C' ? 1 : -1;
    }

    for (int b = 1; b <= whichBucket(N); ++ b)
        buildBucket(b);

    int Q = 0;
    cin >> Q;
    assert(1 <= Q && Q <= 500000);

    for (int i = 1; i <= Q; ++ i) {
        int l, r;
        cin >> l >> r;
        assert(1 <= l && l <= r && r <= N);
        queries[l].emplace_back(r, i);
    }

    vector <int> stk;
    for (int i = N; i; -- i) {
        if (v[i] == -1) {
            stk.push_back(i);
            updatePos(i, 1);
        }
        else {
            if (!stk.empty()) {
                updatePos(stk.back(), -1);
                stk.pop_back();
            }
        }
        for (auto qr: queries[i]) {
            const int l = i, r = qr.r;
            answers[qr.pos] = upper_bound(stk.rbegin(), stk.rend(), r) - stk.rbegin() - query(l, r).minSuf;
        }
    }

    for (int i = 1; i <= Q; ++ i)
        cout << answers[i] << '\n';
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...