[bzoj2120][数颜色] (暴力 or 分块)
2017-01-16 09:20
363 查看
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 ,utop,qtop,ans ,cnt[M]; struct Update { int pos,eld,now; }U ; 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 ; inline void prepare() { static int nowlist ; 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; }
相关文章推荐
- 【BZOJ】2453: 维护队列【BZOJ】2120: 数颜色 二分+分块(暴力能A)
- 【BZOJ 2120】 数颜色 (分块,暴力)
- bzoj2120 数颜色 分块
- bzoj 2120: 数颜色(分块)
- bzoj2120 数颜色 分块
- BZOJ 2120 数颜色 暴力
- bzoj 2120 : 数颜色 分块
- 【BZOJ 2120】 数颜色 (乱搞分块,直指暴力)
- bzoj 2120 数颜色 莫队超级大暴力
- BZOJ2120 数颜色(分块)
- BZOJ2120 数颜色 分块
- Bzoj 2453: 维护队列 && Bzoj 2120: 数颜色 分块,bitset
- [树状数组套权值线段树 || 分块] BZOJ 2120 数颜色 & BZOJ 2453 维护队列
- BZOJ 2120: 数颜色 && 2453: 维护队列 【带修莫队版题【也可以学黄学长分块
- 【bzoj2453】维护队列/【bzoj2120】数颜色 分块+二分
- BZOJ[2120]数颜色/BZOJ[2453]维护队列 分块
- 【BZOJ2453】维护队列/【BZOJ2120】数颜色 分块
- Bzoj 2120: 数颜色 && 2453: 维护队列 莫队,分块,bitset
- 【BZOJ-2453&2120】维护队列&数颜色 分块 + 带修莫队算法
- 【分块】bzoj2120 数颜色