题意
原题链接
给定序列 \(a\),每次查询一个区间 \([l,r]\) 中有多少个不同的数,或进行单点修改。
sol
如果不修改的话,本题就是普通莫队 [luoguSP3267] D-query
由于有修改,所以需要再增加一维,记录这次查询是在多少次修改以后查询的,然后在莫队代码后面添加对修改次数的处理,即暴力修改和还原操作。
排序时,按照先左端点块,再右端点块,最后修改次数的顺序排序,后两项可以进行奇偶性优化。每一块的大小为 \(\lfloor n^{\frac{2}{3}}\rfloor\),均摊时间复杂度为 \(O(n^{\frac{5}{3}})\)。
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N = 150005, M = 1000005;
int n, m;
int c[N];
int buc[M], ans[N], block[N], res = 0;
PII modify[N];
struct Ask{
int l, r, t, id;
bool operator< (const Ask &W) const {
if (block[l] != block[W.l]) return block[l] < block[W.l];
if (block[r] != block[W.r]) return block[r] < block[W.r];
return t < W.t;
}
} queries[N];
void add(int x){
if (!buc[x]) res ++ ;
buc[x] ++ ;
}
void del(int x){
buc[x] -- ;
if (!buc[x]) res -- ;
}
int main(){
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i ++ ) scanf("%d", &c[i]);
int qcnt = 0, mcnt = 0;
for (int i = 1; i <= m; i ++ ){
char op[2];
int x, y;
scanf("%s%d%d", op, &x, &y);
if (*op == 'Q') qcnt ++ , queries[qcnt] = {x, y, mcnt, qcnt};
else modify[ ++ mcnt] = {x, y};
}
int Sz = pow(n, 0.667);
int bcnt = ceil(1.0 * n / Sz);
for (int i = 1; i <= bcnt; i ++ )
for (int j = (i - 1) * Sz + 1; j <= min(n, i * Sz); j ++ )
block[j] = i;
sort(queries + 1, queries + qcnt + 1);
int l = 1, r = 0, time = 0;
for (int i = 1; i <= qcnt; i ++ ){
int ql = queries[i].l, qr = queries[i].r, qt = queries[i].t;
while (l > ql) add(c[ -- l]);
while (r < qr) add(c[ ++ r]);
while (l < ql) del(c[l ++ ]);
while (r > qr) del(c[r -- ]);
while (time < qt) {
time ++ ;
if (ql <= modify[time].x && modify[time].x <= qr) {
add(modify[time].y);
del(c[modify[time].x]);
}
swap(modify[time].y, c[modify[time].x]);
}
while (time > qt) {
if (ql <= modify[time].x && modify[time].x <= qr) {
add(modify[time].y);
del(c[modify[time].x]);
}
swap(modify[time].y, c[modify[time].x]);
time -- ;
}
ans[queries[i].id] = res;
}
for (int i = 1; i <= qcnt; i ++ ) printf("%d\n", ans[i]);
return 0;
}
蒟蒻犯的若至错误
- 忘排序了 awa