带修莫队模板

取分块大小 \(n^\frac{2}{3}\) 最优。
例题:数颜色

#include<bits/stdc++.h>

using namespace std;

using i64 = long long;

const int N = 1e6 + 5;
int cnt[N], a[N];

struct query {
    int l, r, t, id;//加入时间戳
};

struct modfiy {
    int pos, val;
};

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

    int n, m;
    cin >> n >> m;

    int M = pow(n, 2.0 / 3.0);

    for (int i = 1; i <= n; i ++)
        cin >> a[i];

    int cntc = 0, cntq = 0;
    vector<query> q;
    vector<modfiy> c;
    for (int i = 0; i < m; i ++) {
        char op;
        int l, r;
        cin >> op >> l >> r;
        if (op == 'Q') {
            int qt = c.size();
            q.push_back({l, r, qt, (int)q.size()});
        } else {
            c.push_back({l, r});
        }
    }
	//排序与普通莫队不同
    sort(q.begin(), q.end(), [&M](query x, query y) {
        return (((x.l / M) ^ (y.l / M)) ? x.l < y.l : ((x.r / M) ^ (y.r / M)) ? x.r < y.r : x.t < y.t);
    });

    int l = 1, r = 0, time = 0, now = 0;
    vector<int> ans(q.size());
    for (int i = 0; i < q.size(); i ++) {
        auto [ql, qr, qt, id] = q[i];

        while (l < ql)  now -= !--cnt[a[l++]];
        while (l > ql) now += !cnt[a[--l]]++;
        while (r < qr) now += !cnt[a[++r]]++;
        while (r > qr) now -= !--cnt[a[r--]];

        while (time < qt) {
            if (ql <= c[time].pos && c[time].pos <= qr)
                now -= !--cnt[a[c[time].pos]] - !cnt[c[time].val]++;
            swap(a[c[time].pos], c[time].val);
            ++time;
        }
        while (time > qt) {
            --time;
            if (ql <= c[time].pos && c[time].pos <= qr)
                now -= !--cnt[a[c[time].pos]] - !cnt[c[time].val]++;
            swap(a[c[time].pos], c[time].val);
        }
        ans[id] = now;
    }

    for (int i = 0; i < q.size(); i ++)
        cout << ans[i] << "\n";

    return 0;
}

posted @ 2024-07-17 12:37  Ke_scholar  阅读(4)  评论(0编辑  收藏  举报