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

来源:互联网 发布:php发送短信 编辑:程序博客网 时间:2024/04/30 02:51

……学莫队QwQ    好神啊QwQ

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

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

先把询问按照

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

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

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

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

#include<cmath>#include<cstdio>#include<cctype>#include<algorithm>#define MAXN 10005using 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] ;elsereturn 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;}


0 0