[BZOJ 2120]数颜色(带修改莫队)
Description
墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会像你发布如下指令: 1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。 2、 R P Col 把第P支画笔替换为颜色Col。为了满足墨墨的要求,你知道你需要干什么了吗?
Solution
看别人的代码学习了带修改的莫队
对于每个询问记录一个修改到的时间点,按[l所在的块,r所在的块,修改时间]排序
暴力处理就好啦…
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #define MAXN 10005 using namespace std; int n,m,block,col[MAXN]; int vis[MAXN*100],num[MAXN*100],last[MAXN],tot=0,cnt=0,ans=0,res[MAXN]; int read() { int x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){ if(c=='-')f=-1;c=getchar(); } while(c>='0'&&c<='9'){ x=(x<<1)+(x<<3)+c-'0';c=getchar(); } return x*f; } struct Node1 { int pos,c,pre; Node1(int pos=0,int c=0,int pre=0):pos(pos),c(c),pre(pre){} }modify[1005]; struct Node2 { int l,r,now,id; Node2(int l=0,int r=0,int now=0,int id=0):l(l),r(r),now(now),id(id){} bool operator < (const Node2 x) const { if((l-1)/block==(x.l-1)/block) { if((r-1)/block==(x.r-1)/block) return now<x.now; else return (r-1)/block<(x.r-1)/block; } else return (l-1)/block<(x.l-1)/block; } }query[MAXN]; void work(int pos) { if(vis[pos]) { --num[col[pos]]; if(!num[col[pos]])ans--; } else { if(!num[col[pos]])ans++; ++num[col[pos]]; } vis[pos]^=1; } int main() { n=read(),m=read(); block=sqrt(n+0.1); for(int i=1;i<=n;i++) col[i]=read(),last[i]=col[i]; for(int i=1;i<=m;i++) { char opt=getchar(); while(opt!='Q'&&opt!='R')opt=getchar(); int x=read(),y=read(); if(opt=='Q') {++cnt,query[cnt]=Node2(x,y,tot,cnt);} else { modify[++tot]=Node1(x,y,last[x]); last[x]=y; } } sort(query+1,query+1+cnt); int l,r; l=r=1,work(1); for(int i=1;i<=cnt;i++) { for(int j=query[i-1].now+1;j<=query[i].now;j++) { if(vis[modify[j].pos]) { work(modify[j].pos); col[modify[j].pos]=modify[j].c; work(modify[j].pos); } else col[modify[j].pos]=modify[j].c; } for(int j=query[i-1].now;j>query[i].now;j--) { if(vis[modify[j].pos]) { work(modify[j].pos); col[modify[j].pos]=modify[j].pre; work(modify[j].pos); } else col[modify[j].pos]=modify[j].pre; } while(l<query[i].l)work(l++); while(l>query[i].l)work(--l); while(r>query[i].r)work(r--); while(r<query[i].r)work(++r); res[query[i].id]=ans; } for(int i=1;i<=cnt;i++) printf("%d\n",res[i]); return 0; }