Editorial for Dãy số Teto


Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.
#include <bits/stdc++.h>
using namespace std;

using int64 = long long;

const int MOD = 998244353;
const int H = 30;

const int MAX_N = 100000;
const int MAX_Q = 100000;
const int MAX_OPS = MAX_N + MAX_Q + 5;

// Around 48M nodes.
// sizeof(Node) = 20 bytes.
// Total memory ~= 960 MB decimal ~= 916 MiB.
const int MAX_NODE = 4 * H * MAX_OPS + 5;

struct Node {
    int left;
    int right;
    int cover;
    int cnt;
    int ans;
};

Node d[MAX_NODE];

int pow2mod[H + 1];
int fullAns[H + 1];

int nodeCnt = 0;

inline int newNode() {
    ++nodeCnt;
    return nodeCnt;
}

inline int addMod(int a, int b) {
    int s = a + b;
    if (s >= MOD) s -= MOD;
    return s;
}

void precompute() {
    pow2mod[0] = 1;
    for (int i = 1; i <= H; i++) {
        pow2mod[i] = 2LL * pow2mod[i - 1] % MOD;
    }

    fullAns[0] = 1;
    for (int h = 1; h <= H; h++) {
        long long factor = 2LL + pow2mod[h - 1];
        fullAns[h] = 1LL * fullAns[h - 1] * (factor % MOD) % MOD;
    }
}

inline void pull(int id, int h) {
    if (d[id].cover > 0) {
        d[id].cnt = pow2mod[h];
        d[id].ans = fullAns[h];
        return;
    }

    if (h == 0) {
        d[id].cnt = 0;
        d[id].ans = 0;
        return;
    }

    int left = d[id].left;
    int right = d[id].right;

    int cntL = left ? d[left].cnt : 0;
    int cntR = right ? d[right].cnt : 0;
    int ansL = left ? d[left].ans : 0;
    int ansR = right ? d[right].ans : 0;

    int cnt = cntL + cntR;
    if (cnt >= MOD) cnt -= MOD;
    d[id].cnt = cnt;

    int res = addMod(ansL, ansR);
    res = (res + 1LL * ansL * cntR) % MOD;
    d[id].ans = res;
}

void update(
    int id,
    int64 L,
    int64 R,
    int64 qL,
    int64 qR,
    int delta,
    int h
) {
    if (qR <= L || R <= qL) {
        return;
    }

    if (qL <= L && R <= qR) {
        d[id].cover += delta;
        pull(id, h);
        return;
    }

    int64 M = (L + R) >> 1;

    if (qL < M) {
        if (!d[id].left) {
            d[id].left = newNode();
        }
        update(d[id].left, L, M, qL, qR, delta, h - 1);
    }

    if (M < qR) {
        if (!d[id].right) {
            d[id].right = newNode();
        }
        update(d[id].right, M, R, qL, qR, delta, h - 1);
    }

    pull(id, h);
}

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

    precompute();

    int n, q;
    cin >> n >> q;

    const int64 DOMAIN_L = 0;
    const int64 DOMAIN_R = 1LL << H; // [0, 2^60)

    int root = newNode();

    for (int i = 0; i < n; i++) {
        int64 l, r;
        cin >> l >> r;

        update(root, DOMAIN_L, DOMAIN_R, l, r + 1, +1, H);
    }

    cout << d[root].ans << '\n';

    for (int i = 0; i < q; i++) {
        int t;
        int64 u, v;
        cin >> t >> u >> v;

        if (t == 1) {
            update(root, DOMAIN_L, DOMAIN_R, u, v + 1, +1, H);
        } else {
            update(root, DOMAIN_L, DOMAIN_R, u, v + 1, -1, H);
        }

        cout << d[root].ans << '\n';
    }

    return 0;
}

Comments

Please read the guidelines before commenting.


There are no comments at the moment.