您的位置:首页 > 运维架构

BZOJ 2120: 数颜色 && 2453: 维护队列 【带修莫队版题【也可以学黄学长分块

2017-01-18 15:33 603 查看
……学莫队QwQ    好神啊QwQ

复杂度什么的xjb讨论一下感觉好像挺对的23333

加个修改就相当于变成三维的查询……直接用三个指针,维护当前记录的左端点右端点和时间,

先把询问按照

    第一关键字:左端点所在的块

    第二关键字:右端点所在的块

    第三关键字:前一个修改操作的时间

排序,然后xjb暴力做,yy一下可以证明……块大小是N^(2/3)的时候最优  于是就这么写咯……和普通莫队……没啥区别?

#include<cmath>
#include<cstdio>
#include<cctype>
#include<algorithm>
#define MAXN 10005
using namespace std;	int n,m;
inline int read(){
register int ch = getchar();
while(!isdigit(ch))	ch = getchar();
register int rtn = 0 ;
while(isdigit(ch))	rtn = rtn*10 + ch - '0' , ch = getchar() ;
return rtn;
}

int a[MAXN] ;
int col[MAXN] ;
int yjq[MAXN] , laekov ;

struct ASK{
int id,l,r,pre;
ASK(){}
ASK(int id,int l,int r,int pre):
id(id),l(l),r(r),pre(pre){}
bool operator < (const ASK ano) const {
if(yjq[l]==yjq[ano.l])
return yjq[r]==yjq[ano.r] ?
pre < ano.pre :
yjq[r] < yjq[ano.r] ;
else
return yjq[l] < yjq[ano.l] ;
}
}ask[MAXN];	int cnt_ask;
int ans[MAXN];

struct MODIFY{
int id,pos,v,pre;
MODIFY(){}
MODIFY(int id,int pos,int v,int pre):
id(id),pos(pos),v(v),pre(pre){}
}mdf[MAXN];	int cnt_mdf;

int tot = 0 ;
int cnt[1000006] ;
inline void add(int x) {tot += (++cnt[x])==1 ;}
inline void del(int x) {tot -= !(--cnt[x]) ;}

inline void work(){
for(int i=1;i<=n;++i)	col[i] = a[i] ;
int L=1,R=1,TIME=0;
add(col[L]);
for(int i=1;i<=cnt_ask;++i){
int l = ask[i].l , r = ask[i].r , tim = ask[i].pre ;
while(TIME<tim){
++TIME;
int pos = mdf[TIME].pos;
col[pos] = mdf[TIME].v;
if(pos>=L&&pos<=R)
del(mdf[TIME].pre) , add(mdf[TIME].v);
}
while(TIME>tim){
col[mdf[TIME].pos] = mdf[TIME].pre;
int pos = mdf[TIME].pos;
if(pos>=L&&pos<=R)
del(mdf[TIME].v) , add(mdf[TIME].pre);
--TIME;
}
while(L<l)	del(col[L++]);
while(L>l)	add(col[--L]);
while(R<r)	add(col[++R]);
while(R>r)	del(col[R--]);
ans[ask[i].id] = tot ;
}
}

char opt[5];
int now_pre = 0 ;
int read_x,read_y;
int main(){
freopen("1.in","r",stdin);
n = read() , m = read() ;
laekov = pow(n,2.0/3.0);
for(int i=1;i<=n;++i)	a[i] = col[i] = read() ;
for(int i=1;i<=m;++i){
scanf("%s",opt) , read_x = read() , read_y = read();
if(opt[0]=='Q')
ask[++cnt_ask] = ASK(cnt_ask,read_x,read_y,now_pre);
else{
mdf[++cnt_mdf] = MODIFY(cnt_mdf,read_x,read_y,col[read_x]);
col[read_x] = read_y ;
now_pre = cnt_mdf ;
}
}

sort(ask+1,ask+cnt_ask+1);

work();

for(int i=1;i<=cnt_ask;++i)
printf("%d\n",ans[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: