您的位置:首页 > 其它

[BZOJ2120]数颜色(带修改莫队)

2017-03-06 22:40 330 查看

题目描述

传送门

题解

和BZOJ2453相同,在这里可以看到分块的做法

而这道题同时又是一道带修莫队裸题

带修莫队大体方法如下:

1、将修改询问离线并分开,记录每一个修改之前最近的一次询问的编号

2、分块之后将区间排序,关键字为:左端点块的编号、右端点块的编号、记录的最近一次修改的编号

3、在查询每一次询问之前,判断当前做过的修改是否恰好是这次询问需要的修改,如果不够将其修改,修改多了的话恢复回去,注意如果修改的位置在前一个询问的区间内要更新答案

4、转移询问和普通莫队相同

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define N 10005

int n,m,cq,cc,block,now,ans;
struct data{int x,y,t,id,ans;}q
,ch
;
int c
,num
,last
,cnt[N*100];

int cmp(data a,data b)
{
return num[a.x]<num[b.x]||(num[a.x]==num[b.x]&&num[a.y]<num[b.y])||(num[a.x]==num[b.x]&&num[a.y]==num[b.y]&&a.t<b.t);
}
void modui(int x,int y,int val)
{
for (int i=x;i<=y;++i)
{
if (val==1)
{
if (!cnt[c[i]]) ++ans;
++cnt[c[i]];
}
else
{
--cnt[c[i]];
if (!cnt[c[i]]) --ans;
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i) scanf("%d",&c[i]);
block=sqrt(n);
for (int i=1;i<=n;++i) num[i]=(i-1)/block+1;
for (int i=1;i<=m;++i)
{
char opt=getchar();
while (opt!='R'&&opt!='Q') opt=getchar();
if (opt=='R')
{
++cc;
scanf("%d %d",&ch[cc].x,&ch[cc].y);
}
else
{
++cq;q[cq].id=cq;
scanf("%d %d",&q[cq].x,&q[cq].y);
q[cq].t=cc;
}
}
sort(q+1,q+cq+1,cmp);now=q[1].t;
for (int i=1;i<=q[1].t;++i)
{
last[i]=c[ch[i].x];
c[ch[i].x]=ch[i].y;
}
modui(q[1].x,q[1].y,1);q[q[1].id].ans=ans;
for (int i=2;i<=cq;++i)
{
if (now<q[i].t)
for (int j=now+1;j<=q[i].t;++j)
{
if (ch[j].x>=q[i-1].x&&ch[j].x<=q[i-1].y)
{
--cnt[c[ch[j].x]];
if (!cnt[c[ch[j].x]]) --ans;
if (!cnt[ch[j].y]) ++ans;
++cnt[ch[j].y];
}
last[j]=c[ch[j].x];
c[ch[j].x]=ch[j].y;
}
else if (now>q[i].t)
for (int j=now;j>q[i].t;--j)
{
if (ch[j].x>=q[i-1].x&&ch[j].x<=q[i-1].y)
{
--cnt[c[ch[j].x]];
if (!cnt[c[ch[j].x]]) --ans;
if (!cnt[last[j]]) ++ans;
++cnt[last[j]];
}
c[ch[j].x]=last[j];
}
now=q[i].t;
if (q[i].x>q[i-1].x) modui(q[i-1].x,q[i].x-1,-1);
else modui(q[i].x,q[i-1].x-1,1);
if (q[i].y>q[i-1].y) modui(q[i-1].y+1,q[i].y,1);
else modui(q[i].y+1,q[i-1].y,-1);
q[q[i].id].ans=ans;
}
for (int i=1;i<=cq;++i) printf("%d\n",q[i].ans);
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: