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;
}
浙公网安备 33010602011771号