您的位置:首页 > 其它

BSOJ4559:数颜色 带修改莫队算法

2016-02-18 14:22 246 查看
4559 -- 【模拟试题】数颜色

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≤20000,所有的输入数据中出现的所有整数均大于等于1且不超过10^6。

再记录一个修改序列,序列里记录pos,color,pre_color(修改前颜色)

cnt_change和cnt_query分别代表修改序列和查询序列的元素个数。

询问序列里再记录一个tim时间标记,每一次询问对应最近的一个修改,即tim(i)=cnt_change

按照(l->r->tim)的优先级排序

记录一个vis数组,表示元素i是否在当前工作序列中

其他的在注释里

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int ww=0,qq=0;
struct alpha
{
int pos,col,pre;
}w[200005];
struct query
{
int l,r,id,tim,ret;
}q[200005];
int belong[200005]={0},block,last[200005];
bool vis[200005]={0};
int ans=0;
int col[200005]={0};
int hash[2000005]={0};
int Ans[200005];
int n,m;
bool cmp1(query a,query b)
{
if(belong[a.l]==belong[b.l]&&a.r==b.r)return a.tim<b.tim;
if(belong[a.l]==belong[b.l])return a.r<b.r;
return a.l<b.l;
}
void Getdata(int x)
{
if(vis[x])
{
if(--hash[col[x]]==0)ans--;
}
else
{
if(++hash[col[x]]==1)ans++;
}
vis[x]^=1;
}
void Modify(int x,int c)
{
if(vis[x])
{
Getdata(x);
col[x]=c;
Getdata(x);
}
else col[x]=c;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&col[i]),last[i]=col[i];
block=pow(n,2.0/3);
for(int i=1;i<=n;i++)belong[i]=(i-1)/block+1;
for(int i=1;i<=m;i++)
{
char cmd;
int x,y;
cin>>cmd;
scanf("%d%d",&x,&y);
if(cmd=='R')
{
w[++ww].pos=x;w[ww].col=y;w[ww].pre=last[x];
last[x]=y;
}
if(cmd=='Q')
{
q[++qq].l=x;q[qq].r=y;q[qq].id=qq;q[qq].tim=ww;
}
}
sort(q+1,q+qq+1,cmp1);
int l=1,r=0;
for(int i=1;i<=qq;i++)
{

for(int j=q[i-1].tim+1;j<=q[i].tim;j++)Modify(w[j].pos,w[j].col);//每新来一个点,把它之前需要修改的进行修改
for(int j=q[i-1].tim;j>q[i].tim;j--)Modify(w[j].pos,w[j].pre);//时间回流,因为排序后的序列不是时间有序的,可能在询问时已经多做了时间轴之后的修改,要改回去。
for(;r<q[i].r;)Getdata(++r);
for(;r>q[i].r;)Getdata(r--);
for(;l<q[i].l;)Getdata(l++);
for(;l>q[i].l;)Getdata(--l);
Ans[q[i].id]=ans;//hash排序
}
for(int i=1;i<=qq;i++)printf("%d\n",Ans[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: