bzoj 2120 数颜色
Posted 小时のblog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 2120 数颜色相关的知识,希望对你有一定的参考价值。
题目描述
墨墨购买了一套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支画笔中共有几种不同颜色的画笔。
输入输出样例
输入样例#1:
6 5
1 2 3 4 5 5
Q 1 4
Q 2 6
R 1 2
Q 1 4
Q 2 6
输出样例#1:
4
4
3
4
说明
对于100%的数据,N≤10000,M≤10000,修改操作不多于1000次,所有的输入数据中出现的所有整数均大于等于1且不超过10^6。
来源:bzoj2120
题解:
带修改的莫队 luogu wa一个点,bzoj A 了。
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define maxn 1000005 using namespace std; int n,m,a[maxn],cp[maxn],c[maxn],cnt,tim,ans,t,L,R; struct Query{ int l,r,id,pos,ans,t; }q[maxn]; struct Change{ int x,y,bf; }r[maxn]; bool cmp_id(Query a,Query b){ return a.id<b.id; } bool cmp(Query a,Query b){ if(a.pos!=b.pos)return a.pos<b.pos; if(a.r!=b.r)return a.r<b.r; return a.t<b.t; } void timdel(int x,int to){ if(L<=x&&x<=R){ if(c[a[x]]==1)ans--;c[a[x]]--; a[x]=to;if(c[a[x]]==0)ans++;c[a[x]]++; }else{ a[x]=to; } } void add(int x){ if(c[a[x]]==0)ans++; c[a[x]]++; } void del(int x){ if(c[a[x]]==1)ans--; c[a[x]]--; } void slove(){ L=1;R=0;t=0; sort(q+1,q+cnt+1,cmp); for(int i=1;i<=n;i++){ while(t>q[i].t)timdel(r[t].x,r[t].bf),t--; while(t<q[i].t)t++,timdel(r[t].x,r[t].y); while(L<q[i].l)del(L++); while(L>q[i].l)add(--L); while(R>q[i].r)del(R--); while(R<q[i].r)add(++R); q[i].ans=ans; } } int main(){ scanf("%d%d",&n,&m);int size=(int)sqrt(n); for(int i=1;i<=n;i++)scanf("%d",&a[i]),cp[i]=a[i]; for(int i=1;i<=m;i++){ char s[2];int x,y; cin>>s>>x>>y; if(s[0]==‘Q‘){ q[++cnt].l=x;q[cnt].r=y;q[cnt].id=cnt; q[cnt].t=tim;q[cnt].pos=(x-1)/size+1; }else{ r[++tim].x=x;r[tim].y=y;r[tim].bf=cp[x]; cp[x]=y; } } slove(); sort(q+1,q+cnt+1,cmp_id); for(int i=1;i<=cnt;i++)printf("%d\n",q[i].ans); return 0; }
以上是关于bzoj 2120 数颜色的主要内容,如果未能解决你的问题,请参考以下文章