1. 程式人生 > >2018.12.30【國家集訓隊】【洛谷P1903】數顏色 / 維護佇列(帶修莫隊)

2018.12.30【國家集訓隊】【洛谷P1903】數顏色 / 維護佇列(帶修莫隊)

傳送門


解析:

這道題好像以前在BZOJ上做過。

但是因為BZOJ資料較水,所以被我複雜度不對的程式碼搞過去了。。

真正的排序策略應該是這樣的:

塊大小設定成 n 2 3 n^{\frac{2}{3}}


左端點塊不同就按照左端點塊排序。
右端點塊不同根據左端點塊標號的奇偶性排序。
不然就按照時間戳的順序排個序。

每次暴力修改時間戳,然後調整塊的左右端點。

這樣複雜度才是真正的 O ( n 5 3

) O(n^{\frac{5}{3}})

證明自己用勢能分析一下就行了。


程式碼:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const

inline
int getint(){ re int num; re char c; while(!isdigit(c=gc()));num=c^48; while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48); return num; } inline void outint(int a){ static char ch[23]; if(a==0)pc('0'); while(a)ch[++ch[0]]=a-a/10*10,a/=10; while(ch[0])pc(ch[ch[0]--]^48); } inline char getalpha(){ re char c; while(!isalpha(c=gc())); return c; } cs int N=100005,M=1000006; int now,ans[N],l=1,r=0,cur; int pre[N],pos[N],col[N],COL[N],cnt[M],tim[N]; int idxC,qcnt; int B,block[N],bcnt; struct Query{ int l,r,tim,id,pre; friend bool operator<(cs Query &a,cs Query &b){ if(block[a.l]^block[b.l])return block[a.l]<block[b.l]; if(block[a.r]^block[b.r])return (block[a.l]&1)^(a.r>b.r); return a.pre<b.pre; } }q[N]; inline void tim_r(int cur){ if(l<=pos[cur]&&pos[cur]<=r){ --cnt[COL[pos[cur]]]; if(!cnt[COL[pos[cur]]])--now; } pre[cur]=COL[pos[cur]]; COL[pos[cur]]=col[cur]; if(l<=pos[cur]&&pos[cur]<=r){ if(!cnt[COL[pos[cur]]])++now; ++cnt[COL[pos[cur]]]; } } inline void tim_l(int cur){ if(l<=pos[cur]&&pos[cur]<=r){ --cnt[COL[pos[cur]]]; if(!cnt[COL[pos[cur]]])--now; } COL[pos[cur]]=pre[cur]; if(l<=pos[cur]&&pos[cur]<=r){ if(!cnt[COL[pos[cur]]])++now; ++cnt[COL[pos[cur]]]; } } inline void tim_adjust(int now){ while(cur<idxC&&tim[cur+1]<=now)tim_r(++cur); while(cur&&tim[cur]>now)tim_l(cur--); } inline void add(int pos){ if(!cnt[COL[pos]])++now; ++cnt[COL[pos]]; } inline void del(int pos){ --cnt[COL[pos]]; if(!cnt[COL[pos]])--now; } int n,m; signed main(){ n=getint(); m=getint(); B=pow(n,2.0/3.0); bcnt=1; for(int re i=1;i<=n;++i){ COL[i]=getint(); block[i]=bcnt; if(i%B==0)++bcnt; } for(int re i=1;i<=m;++i){ switch(getalpha()){ case 'Q':{ q[++qcnt].id=qcnt; q[qcnt].tim=i; q[qcnt].l=getint(); q[qcnt].r=getint(); q[qcnt].pre=idxC; break; } case 'R':{ tim[++idxC]=i; pos[idxC]=getint(); col[idxC]=getint(); break; } } } sort(q+1,q+qcnt+1); for(int re i=1;i<=qcnt;++i){ tim_adjust(q[i].tim); while(r<q[i].r)add(++r); while(l>q[i].l)add(--l); while(r>q[i].r)del(r--); while(l<q[i].l)del(l++); ans[q[i].id]=now; } for(int re i=1;i<=qcnt;++i){ outint(ans[i]); pc('\n'); } return 0; }