普通不带修改的莫队是对询问二元组 进行分块排序以降低复杂度
对于单点修改的莫队,引入一个时间坐标 t,询问变成三元组:
每一步 有6个方向可走
用类似普通莫队的分块方法,对 l,r 以 的大小进行分块,可以证明复杂度为 ,对 的数据还比较快
对于更新修改操作,只需要维护一个栈,按栈序撤销即可。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 10;
int block,n,m,tot,top;
#define pii pair<int,int>
#define fir first
#define sec second
struct node{
int id,l,r,t;
node(int idi = 0,int li = 0,int ri = 0,int ti = 0) {
id = idi;
l = li;
r = ri;
t = ti;
}
bool operator < (const node &rhs) const {
if(l / block != rhs.l / block) return l < rhs.l;
if(r / block != rhs.r / block) return r < rhs.r;
return t < rhs.t;
}
}q[maxn];
struct ss {
int t,x,y;
ss(int ti = 0,int xi = 0,int yi = 0) {
t = ti;
x = xi;
y = yi;
}
}op[maxn];
char s[maxn];
int a[maxn],curleft,curright,curtime,vis[maxn],res,ans[maxn];
vector<pii> sta;
void modify(int l,int r,int t) {
while(curtime < t) {
curtime++;
if(op[curtime].t == 1) {
int x = op[curtime].x, y = op[curtime].y;
sta.push_back(pii(x,a[x]));
if(curleft <= x && x <= curright) {
vis[a[x]]--;
if(vis[a[x]] == 0) res--;
}
a[x] = y;
if(curleft <= x && x <= curright) {
vis[a[x]]++;
if(vis[a[x]] == 1) res++;
}
}
}
while(curtime > t) {
if(op[curtime].t == 1) {
pii tp = sta.front();
sta.pop_back();
if(curleft <= tp.fir && tp.fir <= curright) {
vis[a[tp.fir]]--;
if(vis[a[tp.fir]] == 0) res--;
}
a[tp.fir] = tp.sec;
if(curleft <= tp.fir && tp.fir <= curright)
vis[a[tp.fir]]++;
if(vis[a[tp.fir]] == 1) res++;
}
curtime--;
}
while(curleft < l) {
vis[a[curleft]]--;
if(vis[a[curleft]] == 0) res--;
curleft++;
}
while(curleft > l) {
curleft--;
vis[a[curleft]]++;
if(vis[a[curleft]] == 1) res++;
}
while(curright < r) {
curright++;
vis[a[curright]]++;
if(vis[a[curright]] == 1) res++;
}
while(curright > r) {
vis[a[curright]]--;
if(vis[a[curright]] == 0) res--;
curright--;
}
}
int main() {
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++)
scanf("%d",&a[i]);
for(int i = 1,x,y; i <= m; i++) {
scanf("%s%d%d",s,&x,&y);
if(s[0] == 'Q') q[++tot] = node(tot,x,y,i),op[i] = ss(0,x,y);
else op[i] = ss(1,x,y);
}
block = min(500,n);
sort(q + 1,q + tot + 1);
res = curleft = curright = curtime = 0;
for(int i = 1; i <= tot; i++) {
modify(q[i].l,q[i].r,q[i].t);
ans[q[i].id] = res;
}
for(int i = 1; i <= tot; i++)
printf("%d\n",ans[i]);
return 0;
}