洛谷1903 数颜色
->题目链接
题目描述
墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会向你发布如下指令:
1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。
2、 R P Col 把第P支画笔替换为颜色Col。
为了满足墨墨的要求,你知道你需要干什么了吗?
输入输出格式
输入格式:
第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数。
第2行N个整数,分别代表初始画笔排中第i支画笔的颜色。
第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。
输出格式:
对于每一个Query的询问,你需要在对应的行中给出一个数字,代表第L支画笔到第R支画笔中共有几种不同颜色的画笔。
输入输出样例
说明
对于100%的数据,N≤50000,M≤50000,所有的输入数据中出现的所有整数均大于等于1且不超过10^6。
本题可能轻微卡常数
来源:bzoj2120
本题数据为洛谷自造数据,使用CYaRon耗时5分钟完成数据制作。
题解:
块状链表+莫队
交了十几二十遍。
皇天不负有心人,最终终于A了。
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #define maxn 50005 using namespace std; typedef double DB; typedef long long LL; struct node { int l,r,id,t; } q[maxn]; struct edge { int pos,val; } re[maxn]; int n,num1,num2,bel[maxn],cnt[maxn*20],num3,pl,pr,pt,c[maxn],cut,sizb,ans[maxn],m; inline int read() { char c=getchar(); int f=1,x=0; while(c<'0'||c>'9'){ if(c=='-') f=-1; c=getchar(); } while(c>='0'&&c<='9') x=x*10+c-48,c=getchar(); return x*f; } void print (int x) { if(x<0) putchar('-'),x=-x; if(x>9) print(x/10); putchar(x%10+'0'); } bool cmp(const node el1,const node el2) { if(el1.l/sizb!=el2.l/sizb) return el1.l<el2.l; if(el1.r/sizb!=el2.r/sizb) if(((el1.l/sizb)&1)) return el1.r<el2.r; else return el1.r>el2.r; return el1.t<el2.t; } void upd(int x) { if(re[x].pos>=pl&&re[x].pos<=pr) { if(!--cnt[c[re[x].pos]]) --num3; if(!cnt[re[x].val]++) ++num3; } swap(re[x].val,c[re[x].pos]); } void query() { pl=pr=pt=0; for(int i=1; i<=cut; i++) { while(pl<q[i].l) if(!--cnt[c[pl++]]) --num3; while(pl>q[i].l) if(!cnt[c[--pl]]++) ++num3; while(pr<q[i].r) if(!cnt[c[++pr]]++) ++num3; while(pr>q[i].r) if(!--cnt[c[pr--]]) --num3; while(pt<q[i].t) upd(++pt); while(pt>q[i].t) upd(pt--); ans[q[i].id]=num3; } } int main() { n=read(),m=read(); sizb=pow(n,2.0/3); for(int i=1; i<=n; i++) c[i]=read(); for(int i=1; i<=m; i++) { char ch=getchar(); if(ch=='Q') { ch=getchar();++cut; q[cut].l=read();q[cut].r=read(); q[cut].id=cut;q[cut].t=num1; } else { ch=getchar(); ++num1; re[num1].pos=read(); re[num1].val=read(); } } sort(q+1,q+cut+1,cmp); query(); for(int i=1; i<=cut; i++) print(ans[i]),puts(" "); return 0; }
我还是喜欢你,像村边老井,深不见底。