您的位置:首页 > 其它

[bzoj2120]数颜色【莫队(带修改)】

2018-01-22 20:47 239 查看
【题目描述】

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

Source

【题解】

 带修改莫队模板题。

先分块,将询问按左端点所在块为第一关键字,右端点所在块为第二关键字,编号(在第几次修改后查询)为第三关键字排序,大力修改。

复杂度分析与无修改莫队相同,块内为O(n*块的大小),块数为O((n/快的大小)^2),当块的大小为n^(2/3)时取到最小值O(n^(5/3))。

/* --------------
user Vanisher
problem bzoj-2120
----------------*/
# include <bits/stdc++.h>
# define ll long long
# define N 1000010
using namespace std;
int read(){
int tmp=0, fh=1; char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
return tmp*fh;
}
struct Q{
int nl,nr,ti,l,r,id;
}q
;
bool cmp(Q x, Q y){
return x.nl<y.nl||x.nl==y.nl&&x.nr<y.nr||x.nl==y.nl&&x.nr==y.nr&&x.ti<y.ti;
}
int las
,now
,h
,n,m,T,numq,numc,p
,nex
,sum,cnt
,ans
;
char opt;
int main(){
n=read(); m=read(); T=pow(n,0.666);
for (int i=1; i<=n; i++) h[i]=now[i]=read();
for (int i=1; i<=m; i++){
scanf("\n%c",&opt);
if (opt=='Q'){
q[++numq].l=read(); q[numq].r=read();
q[numq].nl=q[numq].l/T; q[numq].nr=q[numq].r/T;
q[numq].id=numq;
q[numq].ti=numc;
}
else {
p[++numc]=read();
nex[numc]=read();
las[numc]=now[p[numc]];
now[p[numc]]=nex[numc];
}
}
sort(q+1,q+numq+1,cmp);
int lasl=1, lasr=0, lasq=0;
for (int i=1; i<=numq; i++){
if (q[i].r>lasr)
for (int j=lasr+1; j<=q[i].r; j++)
sum=sum+((cnt[h[j]]++)==0);
else for (int j=lasr; j>q[i].r; j--)
sum=sum-((--cnt[h[j]])==0);
if (q[i].l>lasl)
for (int j=lasl; j<q[i].l; j++)
sum=sum-((--cnt[h[j]])==0);
else for (int j=lasl-1; j>=q[i].l; j--)
sum=sum+((cnt[h[j]]++)==0);
lasr=q[i].r; lasl=q[i].l;
if (q[i].ti>lasq)
for (int j=lasq+1; j<=q[i].ti; j++){
h[p[j]]=nex[j];
if (lasl<=p[j]&&p[j]<=lasr){
sum=sum+((cnt[nex[j]]++)==0);
sum=sum-((--cnt[las[j]])==0);
}
}
else for (int j=lasq; j>q[i].ti; j--){
h[p[j]]=las[j];
if (lasl<=p[j]&&p[j]<=lasr){
sum=sum-((--cnt[nex[j]])==0);
sum=sum+((cnt[las[j]]++)==0);
}
}
lasq=q[i].ti;
ans[q[i].id]=sum;
}
for (int i=1; i<=numq; i++)
printf("%d\n",ans[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: