bzoj 2453: 维护队列
2453: 维护队列
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1079 Solved: 503
[Submit][Status][Discuss]
Description
你小时候玩过弹珠吗?
小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N。为了整个队列鲜艳美观,小朋友想知道某一段连续弹珠中,不同颜色的弹珠有多少。当然,A有时候会依据个人喜好,替换队列中某个弹珠的颜色。但是A还没有学过编程,且觉得头脑风暴太浪费脑力了,所以向你来寻求帮助。
Input
输入文件第一行包含两个整数N和M。
第二行N个整数,表示初始队列中弹珠的颜色。
接下来M行,每行的形式为“Q L R”或“R x c”,“Q L R”表示A想知道从队列第L个弹珠到第R个弹珠中,一共有多少不同颜色的弹珠,“R x c”表示A把x位置上的弹珠换成了c颜色。
Output
对于每个Q操作,输出一行表示询问结果。
Sample Input
2 3
1 2
Q 1 2
R 1 2
Q 1 2
Sample Output
2
1
1
HINT
对于100%的数据,有1 ≤ N ≤ 10000, 1 ≤ M ≤ 10000,小朋友A不会修改超过1000次,所有颜色均用1到10^6的整数表示。
Source
带修莫队
#include<cmath> #include<cstdio> #include<algorithm> #define N 10001 #define M 1000001 using namespace std; int n,m,col[M],sum[M],ans[N]; int tot,now,siz,tmp; struct Query { int l,r,bl,id,tim; bool operator < (Query p) const { if(bl!=p.bl) return bl<p.bl; if(r!=p.r) return r<p.r; return tim<p.tim; } }e[N]; struct Change { int be,af,pos; }g[1001]; void update(int p,int w) { sum[p]+=w; if(sum[p]==1 && w==1) tmp++; if(!sum[p] && w==-1) tmp--; } int main() { scanf("%d%d",&n,&m); siz=sqrt(n); for(int i=1;i<=n;i++) scanf("%d",&col[i]); char s[3]; int l,r; while(m--) { scanf("%s%d%d",s,&l,&r); if(s[0]=='Q') { e[++tot].l=l; e[tot].r=r; e[tot].bl=(l-1)/siz; e[tot].tim=now; e[tot].id=tot; } else { g[++now].pos=l; g[now].af=r; } } sort(e+1,e+tot+1); int L=1,R=0; now=0; for(int i=1;i<=tot;i++) { while(now<e[i].tim) { now++; g[now].be=col[g[now].pos]; if(g[now].pos>=L&&g[now].pos<=R) { update(g[now].be,-1); update(g[now].af,1); } col[g[now].pos]=g[now].af; } while(now>e[i].tim) { if(g[now].pos>=L&&g[now].pos<=R) { update(g[now].af,-1); update(g[now].be,1); } col[g[now].pos]=g[now].be; now--; } while(e[i].l<L) update(col[--L],1); while(e[i].l>L) update(col[L++],-1); while(e[i].r>R) update(col[++R],1); while(e[i].r<R) update(col[R--],-1); ans[e[i].id]=tmp; } for(int i=1;i<=tot;i++) printf("%d\n",ans[i]); }
优化后:
读入优化、1,-1改成 true,false
优化一半
#include<cmath> #include<cstdio> #include<algorithm> #define N 10001 #define M 1000001 using namespace std; int n,m,col[M],sum[M],ans[N]; int tot,now,siz,tmp; struct Query { int l,r,bl,id,tim; bool operator < (Query p) const { if(bl!=p.bl) return bl<p.bl; if(r!=p.r) return r<p.r; return tim<p.tim; } }e[N]; struct Change { int be,af,pos; }g[1001]; void update(int p,bool w) { if(w) { sum[p]++; if(sum[p]==1) tmp++; } else { sum[p]--; if(!sum[p]) tmp--; } } void read(int &x) { x=0; char c=getchar(); while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); } } int main() { read(n); read(m); siz=sqrt(n); for(int i=1;i<=n;i++) read(col[i]); char s[3]; int l,r; while(m--) { scanf("%s",s); read(l); read(r); if(s[0]=='Q') { e[++tot].l=l; e[tot].r=r; e[tot].bl=(l-1)/siz; e[tot].tim=now; e[tot].id=tot; } else { g[++now].pos=l; g[now].af=r; } } sort(e+1,e+tot+1); int L=1,R=0; now=0; for(int i=1;i<=tot;i++) { while(now<e[i].tim) { now++; g[now].be=col[g[now].pos]; if(g[now].pos>=L&&g[now].pos<=R) { update(g[now].be,false); update(g[now].af,true); } col[g[now].pos]=g[now].af; } while(now>e[i].tim) { if(g[now].pos>=L&&g[now].pos<=R) { update(g[now].af,false); update(g[now].be,true); } col[g[now].pos]=g[now].be; now--; } while(e[i].l<L) update(col[--L],true); while(e[i].l>L) update(col[L++],false); while(e[i].r>R) update(col[++R],true); while(e[i].r<R) update(col[R--],false); ans[e[i].id]=tmp; } for(int i=1;i<=tot;i++) printf("%d\n",ans[i]); }