bzoj2120 数颜色
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
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
4
3
4
HINT
对于100%的数据,N≤10000,M≤10000,修改操作不多于1000次,所有的输入数据中出现的所有整数均大于等于1且不超过10^6。
正解:带修改莫队(分块好像也可以来着。。)以前一直以为莫队不能带修改,但当修改次数较少的时候,莫队其实也是一个不错的选择。。
只要记录每次询问之前需要的修改,没修改的就修改,不该修改的就撤回,这样就能够做出这题了。。排序时先按左端点所在块排序,再按右端点所在块排序,最后按需要修改的次数排序。具体操作看代码吧。。
//It is made by wfj_2048~
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define inf 1<<30
#define il inline
#define RG register
#define ll long long
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
using namespace std;
struct node1{ int x,y,last; }r[10010];
struct node2{ int l,r,id,tim,bl,br; }q[10010];
int a[1000010],c[1000010],ans[1000010],last[1000010],n,m,L,R,cnt1,cnt2,Ans,head,block;
char ch[3];
il int gi(){
RG int x=0,q=0; RG char ch=getchar();
while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); if (ch=='-') q=1,ch=getchar();
while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q ? -x : x;
}
il int cmp(const node2 &a,const node2 &b){
if (a.bl==b.bl && a.br==b.br) return a.tim<b.tim;
if (a.bl==b.bl) return a.br<b.br; return a.bl<b.bl;
}
il void change(RG int x,RG int y){
if (L<=x && x<=R){
c[a[x]]--; if (c[a[x]]==0) Ans--; a[x]=y;
c[a[x]]++; if (c[a[x]]==1) Ans++;
}else a[x]=y;
return;
}
il void work(){
n=gi(),m=gi(); block=sqrt(n);
for (RG int i=1;i<=n;++i) last[i]=a[i]=gi();
for (RG int i=1;i<=m;++i){
scanf("%s",ch);
if (ch[0]=='R'){ RG int x=gi(),col=gi(); r[++cnt1].x=x,r[cnt1].y=col,r[cnt1].last=last[x],last[x]=col; }
else{
RG int l=gi(),r=gi(); q[++cnt2].l=l,q[cnt2].r=r,q[cnt2].id=cnt2;
q[cnt2].tim=cnt1,q[cnt2].bl=(l-1)/block+1,q[cnt2].br=(r-1)/block+1;
}
}
sort(q+1,q+cnt2+1,cmp); L=1,R=0,head=0,Ans=0;
for (RG int i=1;i<=cnt2;++i){
while (head<q[i].tim) head++,change(r[head].x,r[head].y);
while (head>q[i].tim) change(r[head].x,r[head].last),head--;
while (L>q[i].l){ L--,c[a[L]]++; if (c[a[L]]==1) Ans++; }
while (R<q[i].r){ R++,c[a[R]]++; if (c[a[R]]==1) Ans++; }
while (L<q[i].l){ c[a[L]]--; if (c[a[L]]==0) Ans--; L++; }
while (R>q[i].r){ c[a[R]]--; if (c[a[R]]==0) Ans--; R--; }
ans[q[i].id]=Ans;
}
for (RG int i=1;i<=cnt2;++i) printf("%d\n",ans[i]); return;
}
int main(){
File("color");
work();
return 0;
}