思想:
不修改的时间复杂度 为n*logn 修改的n*pow(n,0.6666)
在队列里通过l,r 更新区间的答案;
不过要分 根号n 的版块 进行(特殊)排序;
代码:

struct sfs{ int l,r,pos,id; // pos 板块 bool operator <(const sfs b)const { if(pos==b.pos) { if(r==b.r) return l<b.l; return r<b.r; } return pos<b.pos; } }p[M];
栗子很重要,要看:

HH 有一串由各种漂亮的贝壳组成的项链。HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一段贝壳,思考它们所表达的含义。HH 不断地收集新的贝壳,因此他的项链变得越来越长。有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答,因为项链实在是太长了。于是,他只好求助睿智的你,来解决这个问题。 输入格式 第一行:一个整数 ,表示项链的长度。 第二行: 个整数,表示依次表示项链中贝壳的编号(编号为 到 之间的整数)。 第三行:一个整数 ,表示HH询问的个数。 接下来 行:每行两个整数, 和 ,表示询问的区间。 输出格式 行,每行一个整数,依次表示询问对应的答案。 样例 输入样例: 6 1 2 3 4 3 5 3 1 2 3 5 2 6 输出样例: 2 2 4 数据范围与提示 , , 。
代码

//1 出现的思想 //2 cmp 的各个的写法 #include <bits/stdc++.h> using namespace std; #define ri register int #define M 1000005 struct sfs{ int l,r,pos,id; // pos 板块 bool operator <(const sfs b)const { if(pos==b.pos) { if(r==b.r) return l<b.l; return r<b.r; } return pos<b.pos; } }p[M]; int ans[M]; int col[M]; int n,m; void readyy() { scanf("%d",&n); for(ri i=1;i<=n;i++) scanf("%d",&col[i]); scanf("%d",&m); int d=int(sqrt(n)+0.5); /// REMEMBER for(ri i=1;i<=m;i++) { int a,b; scanf("%d%d",&a,&b); p[i].pos=a/d; p[i].l=a,p[i].r=b,p[i].id=i; } sort(p+1,p+1+m); } int num[M];int cur; void jia(int a) { if(!num[col[a]]) cur++; num[col[a]]++; } void jian(int a) { if(num[col[a]]==1) cur--; num[col[a]]--; } void solv() { int l=p[1].l; int r=l; jia(r); // 起始点 // 函数此时可以正常编译 莫md while(r<p[1].r) { jia(++r); } ans[p[1].id]=cur; // printf("%d\n",r); for(ri i=2;i<=m;i++) // 是从第二个开始 { // 下面写法 可以 就是让 l,r到达想要的地方。 while(l<p[i].l) jian(l++); // 到达那个的点不用减去,起始的点要减去;以下同理可得 while(l>p[i].l) jia(--l); while(r<p[i].r) jia(++r); while(r>p[i].r) jian(r--); ans[p[i].id]=cur; } for(ri i=1;i<=m;i++) printf("%d\n",ans[i]); } int main(){ readyy(); solv(); return 0; }
修改莫队

struct dian{ int l,r,pos,id,tim; bool operator <(const dian &t)const { if(pos==t.pos) { if(r/d==t.r/d) return tim<t.tim; return r<t.r; } return l<t.l; } }p[M]; void work (int v,int k) { vis[cent[v]]--; cent[v]+=k; vis[cent[v]]++; } void work_tim(int ti,int i) { if(p[i].l<=gai[ti].mubiao&&gai[ti].mubiao<=p[i].r) { work(val[gai[ti].mubiao],-1); work(gai[ti].VAL,1); } swap(val[gai[ti].mubiao],gai[ti].VAL); } d=pow(n,0.6666); for(ri i=1;i<=m;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); if(a==1) { p[++trmp].l=b; p[trmp].r=c; p[trmp].id=trmp;p[trmp].tim=sj; p[trmp].pos=p[trmp].l/d; } else { gai[++sj].mubiao=b; tt[n+sj]=gai[sj].VAL=c; } } sort(p+1,p+trmp+1); sj=0; for(ri i=p[1].l;i<=p[1].r;i++) { work(val[i],1); } int baba; while(sj<p[1].tim) work_tim(++sj,1); while(sj>p[1].tim) work_tim(sj--,1); // li hai for (ANS[p[1].id]=1;vis[ANS[p[1].id]]>0;ANS[p[1].id]++); for(ri i=2;i<=m;i++) { int l=p[i-1].l; int r=p[i-1].r; while(l<p[i].l) work(val[l++],-1); while(r>p[i].r) work(val[r--],-1); while(l>p[i].l) work(val[--l],1); while(r<p[i].r) work(val[++r],1); while(sj<p[i].tim) work_tim(++sj,i); while(sj>p[i].tim) work_tim(sj--,i); //跟新ans }
注意 d的取值为什么有时取 pow(n,0.6666)呢 而不是 int(0.5+sqrt(n))