首页 > 学院 > 开发设计 > 正文

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

2019-11-06 06:23:15
字体:
来源:转载
供稿:网友

题目描述

传送门

题解

和BZOJ2453相同,在这里可以看到分块的做法 而这道题同时又是一道带修莫队裸题 带修莫队大体方法如下: 1、将修改询问离线并分开,记录每一个修改之前最近的一次询问的编号 2、分块之后将区间排序,关键字为:左端点块的编号、右端点块的编号、记录的最近一次修改的编号 3、在查询每一次询问之前,判断当前做过的修改是否恰好是这次询问需要的修改,如果不够将其修改,修改多了的话恢复回去,注意如果修改的位置在前一个询问的区间内要更新答案 4、转移询问和普通莫队相同

代码

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cmath>using namespace std;#define N 10005int n,m,cq,cc,block,now,ans;struct data{int x,y,t,id,ans;}q[N],ch[N];int c[N],num[N],last[N],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);}
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表