会修修的莫队--BZOJ2120: 数颜色
$n \leq 10000$的数列,$m \leq 10000$个操作,一:单点修改;二:查区间不同数字个数。修改数$\leq 1000$,数字$\leq 1000000$。
我不会告诉您这是三种写法的双倍经验题!!
一般可以把查区间不同个数改成:$pre_i$表示$i$之前的一个与她相同的数在哪,然后变成查某个区间$pre_i$在某个范围内的数量。可以主席树,也可分块。修改暴力重构。
方法三:带修莫队。按L块为第一关键字、R块为第二关键字、时间为第三关键字对询问排序,这样时间指针的移动复杂度是块数量的平方乘修改数。
理论上块大小取$n^{\frac{2}{3}}$是最好的,但是注意一下修改数只有1000。。于是求个导画个图象(用电脑)可得块大小280左右时最优。加了个离散化跑得飞起。
1 //#include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 //#include<queue> 6 //#include<time.h> 7 //#include<complex> 8 #include<algorithm> 9 #include<stdlib.h> 10 using namespace std; 11 12 int n,m,lq,lc,tot; 13 #define maxn 10011 14 #define maxm 288 15 int a[maxn],bel[maxn]; 16 struct Ques{int l,r,t,id;}q[maxn]; 17 bool cmp(const Ques a,const Ques b) {return bel[a.l]==bel[b.l]?(bel[a.r]==bel[b.r]?a.t<b.t:a.r<b.r):a.l<b.l;} 18 struct Modi{int x,a,b;}mo[maxn]; 19 20 int lisa[maxn<<1],li; 21 int ss; int cnt[maxn<<1],ans[maxn]; 22 void modify(int p,int type) {cnt[a[p]]+=type; if (type>0) ss+=cnt[a[p]]==1; else ss-=cnt[a[p]]==0;} 23 void timemodify(int L,int R,int p,int v) {if (L<=p && p<=R) modify(p,-1); a[p]=v; if (L<=p && p<=R) modify(p,1);} 24 25 int main() 26 { 27 scanf("%d%d",&n,&lq); m=280; 28 for (int i=1;i<=n;i++) bel[i]=(i-1)/m+1; tot=bel[n]; 29 for (int i=1;i<=n;i++) scanf("%d",&a[i]),lisa[++li]=a[i]; 30 char c; lc=0; 31 for (int i=1,j=0;i<=lq;i++) 32 { 33 while ((c=getchar())!='R' && c!='Q'); 34 if (c=='Q') 35 { 36 j++; scanf("%d%d",&q[j].l,&q[j].r); 37 q[j].id=j; q[j].t=lc; 38 } 39 else 40 { 41 lc++; scanf("%d%d",&mo[lc].x,&mo[lc].b); 42 mo[lc].a=a[mo[lc].x]; a[mo[lc].x]=mo[lc].b; lisa[++li]=mo[lc].b; 43 } 44 } 45 lq-=lc; 46 sort(lisa+1,lisa+1+li); li=unique(lisa+1,lisa+1+li)-lisa-1; 47 for (int i=1;i<=n;i++) a[i]=lower_bound(lisa+1,lisa+1+li,a[i])-lisa; 48 for (int i=1;i<=lc;i++) mo[i].a=lower_bound(lisa+1,lisa+1+li,mo[i].a)-lisa, 49 mo[i].b=lower_bound(lisa+1,lisa+1+li,mo[i].b)-lisa; 50 51 sort(q+1,q+1+lq,cmp); 52 int L=1,R=0,T=lc; ss=0; 53 for (int i=1;i<=lq;i++) 54 { 55 while (T>q[i].t) timemodify(L,R,mo[T].x,mo[T].a),T--; 56 while (T<q[i].t) T++,timemodify(L,R,mo[T].x,mo[T].b); 57 while (L<q[i].l) modify(L,-1),L++; 58 while (L>q[i].l) modify(L-1,1),L--; 59 while (R<q[i].r) modify(R+1,1),R++; 60 while (R>q[i].r) modify(R,-1),R--; 61 ans[q[i].id]=ss; 62 } 63 for (int i=1;i<=lq;i++) printf("%d\n",ans[i]); 64 return 0; 65 }