[bzoj2453]維護隊列_帶修改莫隊
阿新 • • 發佈:2019-02-07
個數 for sort har 關鍵字 pos 一個 ret ()
維護隊列 bzoj-2453
題目大意:給定一個n個數序列,支持查詢區間數的種類數,單點修改。不強制在線。
註釋:$1\le n,m\le 10^5$。
想法:
帶修改莫隊裸題。
如果沒有修改操作的話,我們就正常按照莫隊一樣左右移動區間即可。
有了修改操作的話,我們把塊變成$n^{\frac{2}{3}}$,關鍵字變成:左端點所在塊、右端點所在塊和時間戳。
然後暴力就行了。
Code:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; const int N=10003; struct Query{int l,r,Tim,ID;}q[N]; struct Change{int pos,New,Old;}c[N]; int n,m,s[N],color[N*100],t,Time,now[N],unit,Be[N],ans[N],Ans,l=1,r,T; inline bool cmp(const Query &a,const Query &b) { return Be[a.l]==Be[b.l]?(Be[a.r]==Be[b.r]?a.Tim<b.Tim:a.r<b.r):a.l<b.l; } inline void revise(int x,int d) {color[x]+=d; if(d>0) Ans+=color[x]==1; if(d<0) Ans-=color[x]==0;} inline void going(int x,int d) {if(l<=x&&x<=r) revise(d,1),revise(s[x],-1); s[x]=d;} int main() { scanf("%d%d",&n,&m); unit=pow(n,0.666666); for(int i=1;i<=n;i++) scanf("%d",&s[i]),now[i]=s[i],Be[i]=i/unit+1; for(int i=1;i<=m;i++) { char s[10]; int x,y; scanf("%s%d%d",s+1,&x,&y); if(s[1]==‘Q‘) q[++t]=(Query){x,y,Time,t}; if(s[1]==‘R‘) {c[++Time]=(Change){x,y,now[x]},now[x]=y;} } // printf("Fuck %d\n",t); sort(q+1,q+t+1,cmp); for(int i=1;i<=t;i++) { while(T<q[i].Tim) going(c[T+1].pos,c[T+1].New),T++; while(T>q[i].Tim) going(c[T].pos,c[T].Old),T--; while(l<q[i].l) revise(s[l],-1),l++; while(l>q[i].l) revise(s[l-1],1),l--; while(r<q[i].r) revise(s[r+1],1),r++; while(r>q[i].r) revise(s[r],-1),r--; ans[q[i].ID]=Ans; } for(int i=1;i<=t;i++) printf("%d\n",ans[i]); return 0; }
小結:莫隊其實就是暴力啊。
[bzoj2453]維護隊列_帶修改莫隊