bzoj2120 带修改莫队
题意:中文题
思路:带修改的莫队,基本上是裸题,带上修改的思路就是在原来的基础上加上维护一个时间,就是修改的时间,将修改的时间作为第三关键字排序,每次询问前把不需要修改的恢复,把需要修改的修改,但是并不需要从头到最后遍历,如果上一次查询的时间超出了现在查询的时间,那么只需要将现在查询的下一个修改直到上一次修改到的位置全部恢复,如果上一次查询的时间小于现在查询的时间,那么只需要从上一次查询的下一个修改直到当前查询的前一个修改全部修改即可,在修改或者恢复的时候需要注意一下,有一个标记,标记的作用是记录这次修改的位置是否在上一次计算的答案之内,如果在,那么会对答案造成影响(相当于del掉这个位置的数,再在这个位置上add需要修改的数的影响),如果不在,那么直接将该位置的数字更改即可,初始化的时候q[0].time要初始为cnt(修改的次数),因为在输入的时候每次修改操作都执行了,最后时间复杂度是n^(5/3),最优的分块是unit=n^(2/3)
AC代码:
#include "iostream" #include "string.h" #include "stack" #include "queue" #include "string" #include "vector" #include "set" #include "map" #include "algorithm" #include "stdio.h" #include "math.h" #pragma comment(linker, "/STACK:102400000,102400000") #define ll long long #define endl ("\n") #define bug(x) cout<<x<<" "<<"UUUUU"<<endl; #define mem(a,x) memset(a,x,sizeof(a)) #define mp(x,y) make_pair(x,y) #define pb(x) push_back(x) #define ft first #define sd second #define lrt (rt<<1) #define rrt (rt<<1|1) using namespace std; const ll INF = 1e18+1LL; const int inf = 1e9+1e8; const int N=1e4+100; const ll mod=1e9+7; int n,m,c,cnt,unit,a[N],b[N]; struct Cap_Mo{ int ans[N],num[N*100],vis[N],temp; Cap_Mo(){ mem(vis,0), mem(num,0), temp=0; } struct Qu{ int l,r,id,ti; bool friend operator< (Qu a, Qu b){ if(a.l/unit == b.l/unit){ if(a.r==b.r) return a.ti<b.ti; return a.r<b.r; }return a.l<b.l; } }q[N]; struct Ch{ int p,pre,cur; }re[N]; void add(int x){ if(!num[a[x]]) temp++; num[a[x]]++; vis[x]=1; } void del(int x){ num[a[x]]--; vis[x]=0; if(!num[a[x]]) temp--; } void change(int pos, int now){ if(vis[pos]) del(pos), a[pos]=now, add(pos); else a[pos]=now; } void work(){ q[0].ti=cnt, unit=(int)sqrt(n); sort(q+1,q+1+c); int L=1, R=0; for(int i=1; i<=c; ++i){ for(int j=q[i-1].ti; j>q[i].ti; --j){ change(re[j].p, re[j].pre); ///将不需要修改的恢复 } for(int j=q[i-1].ti+1; j<=q[i].ti; ++j){ change(re[j].p, re[j].cur); ///将需要修改的进行修改 } while(R < q[i].r) add(++R); while(R > q[i].r) del(R--); while(L > q[i].l) add(--L); while(L < q[i].l) del(L++); ans[q[i].id]=temp; } } }Mo; int main(){ scanf("%d %d", &n, &m); for(int i=1; i<=n; ++i){ scanf("%d", a+i); } char ch[5]; int l,r; for(int i=1; i<=m; ++i){//cin>>ch>>l>>r; scanf("%s%d%d", ch, &l, &r); if(ch[0]=='R'){ Mo.re[++cnt].p=l, Mo.re[cnt].cur=r, Mo.re[cnt].pre=a[l], a[l]=r; } else{ Mo.q[++c].l=l, Mo.q[c].r=r, Mo.q[c].id=c, Mo.q[c].ti=cnt; } } Mo.work(); for(int i=1; i<=c; ++i) printf("%d\n",Mo.ans[i]); return 0; }