[bzoj2120][数颜色] (暴力 or 分块)
Description
墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会像你发布如下指令: 1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。 2、 R P Col 把第P支画笔替换为颜色Col。为了满足墨墨的要求,你知道你需要干什么了吗?
Input
第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数。第2行N个整数,分别代表初始画笔排中第i支画笔的颜色。第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。
Output
对于每一个Query的询问,你需要在对应的行中给出一个数字,代表第L支画笔到第R支画笔中共有几种不同颜色的画笔。
Sample Input
6 5 1 2 3 4 5 5 Q 1 4 Q 2 6 R 1 2 Q 1 4 Q 2 6
Sample Output
4 4 3 4
HINT
对于100%的数据,N≤10000,M≤10000,修改操作不多于1000次,所有的输入数据中出现的所有整数均大于等于1且不超过10^6。
2016.3.2新加数据两组by Nano_Ape
Solution
先上简单的暴力,可以水过
#include <stdio.h> #include <string.h> #define M 1000010 inline int Rin() { int x=0,c=getchar(),f=1; for(; c<48||c>57; c=getchar()) if(c==45)f=-1; for(; c>47&&c<58; c=getchar()) x=(x<<1)+(x<<3)+c-48; return x*f; } char c; int g[M],n,m,a[M],top,x,y,i,mark[M],ans; int main() { n=Rin(),m=Rin(); for(i=1; i<=n; i++) { a[i]=Rin(); if(!g[a[i]]) g[a[i]]=++top; a[i]=g[a[i]]; } while(m--) { do c=getchar(); while(c!='Q'&&c!='R'); x=Rin(),y=Rin(); if(c=='Q') { for(i=x,ans=0; i<=y; i++) if(mark[a[i]]!=m) mark[a[i]]=m,ans++; printf("%d\n",ans); } else { if(!g[y])g[y]=++top; a[x]=g[y]; } } return 0; }
一下是莫队的做法
otz menci
#include <math.h> #include <stdio.h> #include <string.h> #include <algorithm> #define N 10010 #define M 1000010 #define RG register #define inline __inline__ __attribute__((always_inline)) inline void Rin(RG int &x) { x=0;RG int c=getchar(),f=1; for(; c<48||c>57; c=getchar()) if(c==45)f=-1; for(; c>47&&c<58; c=getchar()) x=(x<<1)+(x<<3)+c-48; x*=f; } int n,m,block_size,a[N],utop,qtop,ans[N],cnt[M]; struct Update { int pos,eld,now; }U[N]; struct Request{ int tim,l,r,id; bool operator < (const Request &other)const { if(l/block_size == other.l/block_size) { if(r/block_size == other.r/block_size) return tim < other.tim; return r/block_size < other.r/block_size; } return l/block_size < other.l/block_size; } }Q[N]; inline void prepare() { static int nowlist[N]; memcpy(nowlist,a,sizeof a); for(RG int i=1; i<=utop; i++) { U[i].eld=nowlist[U[i].pos]; nowlist[U[i].pos]=U[i].now; } } inline void extend(RG int &tmp,RG int pos,RG int dir) { if(dir == 1) { if(++cnt[a[pos]]==1) tmp++; } else if(--cnt[a[pos]]==0) tmp--; } inline void modify(RG int &tmp,RG int T,RG int l,RG int r,RG int dir) { RG Update x=U[T]; if(dir == 1) { a[x.pos]=x.now; if(x.pos >=l && x.pos <= r) { if(--cnt[x.eld]==0)tmp--; if(++cnt[x.now]==1)tmp++; } } else { if(x.pos >=l && x.pos <= r) { if(--cnt[x.now]==0)tmp--; if(++cnt[x.eld]==1)tmp++; } a[x.pos]=x.eld; } } inline void block_solve() { for(RG int l=1,r=0,ans=0,T=0,i=1; i<=qtop; i++) { while(r < Q[i].r)extend(ans,++r,1); while(r > Q[i].r)extend(ans,r--,-1); while(l > Q[i].l)extend(ans,--l,1); while(l < Q[i].l)extend(ans,l++,-1); while(T < Q[i].tim)modify(ans,++T,l,r,1); while(T > Q[i].tim)modify(ans,T--,l,r,-1); :: ans[Q[i].id]=ans; } } int main() { Rin(n),Rin(m); for(RG int i=1; i<=n; i++) Rin(a[i]); for(RG int i=1; i<=m; i++) { RG char c; do c=getchar(); while(c != 'Q'&&c != 'R'); if(c == 'Q') { ++qtop; Rin(Q[qtop].l),Rin(Q[qtop].r); Q[qtop].id=qtop; Q[qtop].tim=utop; } else { ++utop; Rin(U[utop].pos),Rin(U[utop].now); } } prepare(); block_size=floor(pow(n,2.0/3)+1); std::sort(Q+1,Q+1+qtop); block_solve(); for(RG int i=1; i<=qtop;i++) printf("%d\n",ans[i]); return 0; }