P1903 [国家集训队] 数颜色 题解 带修莫队 模板题

题目链接:https://www.luogu.com.cn/problem/P1903

解题思路完全来自 《算法竞赛》(书)及 oi.wiki

示例程序:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 133333 + 5, maxb = pow(maxn, 2.0 / 3) + 5, maxm = 1e6 + 5;

int n, m, blo, a[maxn], ans[maxn], cnt[maxm], sum, idx1, idx2;

struct Query {
    int id, l, r, t;
} query[maxn];

struct Event {
    int p, c;
} event[maxn];

void add(int c) {
    if (++cnt[c] == 1)
        sum++;
}

void del(int c) {
    if (--cnt[c] == 0)
        sum--;
}

int main() {
    scanf("%d%d", &n, &m);
    blo = pow(n, 2.0/3);
    for (int i = 1; i <= n; i++)
        scanf("%d", a+i);
    for (int i = 0; i < m; i++) {
        char op[2];
        scanf("%s", op);
        if (op[0] == 'Q') { // Q l r
            int l, r;
            scanf("%d%d", &l, &r);
            idx1++;
            query[idx1] = {idx1, l, r, idx2};
        }
        else { // R p c
            int p, c;
            scanf("%d%d", &p, &c);
            event[++idx2] = {p, c};
        }
    }
    sort(query+1, query+idx1+1, [](auto a, auto b) {

        if (a.l / blo != b.l / blo)
            return a.l < b.l;
        if (a.r / blo != b.r / blo)
            return a.r < b.r;
        return a.t < b.t;

      });
    for (int i = 1, l = 1, r = 0, t = 0; i <= idx1; i++) {
        while (l < query[i].l) del(a[l++]);
        while (l > query[i].l) add(a[--l]);
        while (r < query[i].r) add(a[++r]);
        while (r > query[i].r) del(a[r--]);
        for (; t < query[i].t; t++) {
            auto [p, c] = event[t+1];
            int x = a[p];
            if (p >= l && p <= r) {
                del(x);
                add(c);
            }
            a[p] = c;
            event[t+1].c = x;
        }
        for (; t > query[i].t; t--) {
            auto [p, c] = event[t];
            int x = a[p];
            if (p >= l && p <= r) {
                del(x);
                add(c);
            }
            a[p] = c;
            event[t].c = x;
        }
        ans[ query[i].id ] = sum;
    }

    for (int i = 1; i <= idx1; i++)
        printf("%d\n", ans[i]);

    return 0;
}
posted @ 2026-03-04 16:15  quanjun  阅读(1)  评论(0)    收藏  举报