Hướng dẫn giải của Dãy số Teto


Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
#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;
}

Bình luận

Hãy đọc nội quy trước khi bình luận.


Không có bình luận tại thời điểm này.