bzoj2120&&2453 -- 带修改莫队

待修改莫队裸题。。。

当莫队有修改操作时,只要记录每个询问的时间,在两次询问之间修改就可以了。

可以证明时间复杂度是O(n^(5/3))的

具体看代码。

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 #define N 10010
 8 #define M 1000010
 9 struct Q{
10     int l,r,f,F;
11 }a[N];
12 struct U{
13     int x,p,c;
14 }w[N];
15 int x,y,i,j,k,n,m,p,l,r,Res,Cnt,b[N],S,c[M],A[N],Ans[N],L[M];
16 char s[2];
17 bool B[N];
18 inline bool Cmp(Q x,Q y){
19     if(b[x.l]==b[y.l])return x.r<y.r;
20     return b[x.l]<b[y.l];
21 }
22 inline void Update1(int x){
23     B[x]=1;
24     if(++c[A[x]]==1)Res++;
25 }
26 inline void Update2(int x){
27     B[x]=0;
28     if(--c[A[x]]==0)Res--;
29 }
30 inline void Update(int x,int y){
31     if(B[x]){
32         Update2(x);
33         A[x]=y;
34         Update1(x);
35     }else A[x]=y;
36 }
37 int main(){
38     scanf("%d%d",&n,&m);S=sqrt((double)n);
39     for(i=1;i<=n;i++)scanf("%d",&A[i]),L[i]=A[i],b[i]=(i-1)/S+1;
40     for(i=1;i<=m;i++){
41         scanf("%s",s);
42         if(s[0]=='Q')a[++Cnt].f=i,a[Cnt].F=Cnt,scanf("%d%d",&a[Cnt].l,&a[Cnt].r);else scanf("%d%d",&w[i].x,&w[i].c),w[i].p=L[w[i].x],L[w[i].x]=w[i].c;
43     }
44     sort(a+1,a+Cnt+1,Cmp);
45     for(i=l=1,r=0;i<=Cnt;i++){
46         for(j=a[i-1].f+1;j<a[i].f;j++)Update(w[j].x,w[j].c);
47         for(j=a[i-1].f-1;j>a[i].f;j--)Update(w[j].x,w[j].p);
48         while(a[i].r>r)Update1(++r);
49         while(a[i].l<l)Update1(--l);
50         while(a[i].r<r)Update2(r--);
51         while(a[i].l>l)Update2(l++);
52         Ans[a[i].F]=Res;
53     }
54     for(i=1;i<=Cnt;i++)printf("%d
",Ans[i]);
55     return 0;
56 }
bzoj2120
原文地址:https://www.cnblogs.com/gjghfd/p/6742229.html