1. 程式人生 > >洛谷P3380 【模板】二逼平衡樹(樹套樹,樹狀數組,線段樹)

洛谷P3380 【模板】二逼平衡樹(樹套樹,樹狀數組,線段樹)

bre 就是 uniq nlog lin tdi 數組 比較 也有

洛谷題目傳送門

emm。。。題目名寫了個平衡樹,但是這道題的理論復雜度最優解應該還是樹狀數組套值域線段樹吧。

就像dynamic ranking那樣(蒟蒻的Sol,放一個link騙訪問量233)

所有的值(包括初始a數組,操作1、3、4、5的k)全部先丟進去離散化

對於1操作查比它小的數,挑log棵線段樹,找區間小於這個數的個數+1,這個還比較好像

操作2就是dynamic ranking,log棵線段樹一起加減,像靜態主席樹求第k小一樣跳,操作3 dynamic ranking裏也有

操作4先求小於這個數的個數,那麽前驅的排名就等於這個個數,註意特判0就好了。

操作5也是先求排名再去找這個數,排名是小於且等於這個數的個數(等於查小於這個數在值域裏加+1的數排名)

拼命卡常(小技巧,發現當前跳到的點size已經為0了就不用再往下跳了),然而常數還是醜。。。說不定應該破掉非遞歸版跑的比遞歸版多多少少快一點的謠言了?

#include<cstdio>
#include<cstring>
#include<algorithm>
#define RG register
#define R RG int
#define II inline int
#define IV inline void
#define gc          if(++pi==iend)fread(pi=ibuf,1,SZ,stdin)
#define pc(C) *po=C;if(++po==oend)fwrite(po=obuf,1,SZ,stdout)
#define Q b+1,b+L+1 #define lb(X) X=lower_bound(Q,X)-b using namespace std; const int SZ=1<<20,N=50009,M=5000009,INF=2147483647;//卡了空間,M沒到Nlog^2 char ibuf[SZ],obuf[SZ],*pi=ibuf+SZ-1,*po=obuf; const char*iend=ibuf+SZ,*oend=obuf+SZ; IV in(R&x){ gc; while(*pi<‘-‘)gc; x=*pi&15;gc; while
(*pi>‘-‘){x*=10;x+=*pi&15;gc;} } IV out(R x){ if(x>9)out(x/10); pc(x%10|‘0‘); } int n,L,P,a[N],b[N<<1],op[N],ql[N],qr[N],qk[N]; int rt[N],lc[M],rc[M],s[M],ra[20],rs[20]; IV upd(R p,R k,R v){//更新 for(R u,l,r,m,i=p;i<=n;i+=i&-i){ if(!rt[i])rt[i]=++P;u=rt[i];l=1;r=L; while(l^r){ s[u]+=v;m=(l+r)>>1; if(k<=m){r=m;if(!lc[u])lc[u]=++P;u=lc[u];} else {l=m+1;if(!rc[u])rc[u]=++P;u=rc[u];} } s[u]+=v; } } II kth(R p,R k){//求第k小的值 R i,l=1,r=L,m,sum,pa=0,ps=0; for(i=qr[p] ;i;i-=i&-i)ra[++pa]=rt[i]; for(i=ql[p]-1;i;i-=i&-i)rs[++ps]=rt[i]; while(l^r){ sum=0;m=(l+r)>>1; for(i=1;i<=pa;++i)sum+=s[lc[ra[i]]]; for(i=1;i<=ps;++i)sum-=s[lc[rs[i]]]; if(k<=sum){ r=m; for(i=1,p=pa,pa=0;i<=p;++i)ra[++pa]=lc[ra[i]]; for(i=1,p=ps,ps=0;i<=p;++i)rs[++ps]=lc[rs[i]]; } else{ l=m+1;k-=sum; for(i=1,p=pa,pa=0;i<=p;++i)ra[++pa]=rc[ra[i]]; for(i=1,p=ps,ps=0;i<=p;++i)rs[++ps]=rc[rs[i]]; } } return b[l]; } II rank(R p,R x){//求離散化後的值的排名(從0計,也就是小於等於值的數的個數) R i,u,l,r,m,k=0; for(i=qr[p];i;i-=i&-i){ u=rt[i];l=1;r=L; while(s[u]&&l^r){ m=(l+r)>>1; if(x<=m) r=m,u=lc[u]; else k+=s[lc[u]],l=m+1,u=rc[u]; } } for(i=ql[p]-1;i;i-=i&-i){ u=rt[i];l=1;r=L; while(s[u]&&l^r){ m=(l+r)>>1; if(x<=m) r=m,u=lc[u]; else k-=s[lc[u]],l=m+1,u=rc[u]; } } return k; } int main(){ R m,i,rk; in(n);in(m);L=n; for(i=1;i<=n;++i)in(a[i]); memcpy(b,a,(n+1)<<2); for(i=1;i<=m;++i){ in(op[i]);//先存起來 in(ql[i]);if(op[i]!=3)in(qr[i]); in(qk[i]);if(op[i]!=2)b[++L]=qk[i]; } b[++L]=INF;sort(Q);L=unique(Q)-b-1; for(i=1;i<=n;++i) upd(i,lb(a[i]),1); for(i=1;i<=m;++i){ if(op[i]!=2)lb(qk[i]); switch(op[i]){ case 1:out(rank(i,qk[i])+1);pc(\n);break; case 2:out(kth(i,qk[i]));pc(\n);break; case 3:upd(ql[i],a[ql[i]],-1); upd(ql[i],a[ql[i]]=qk[i],1);break; case 4:rk=rank(i,qk[i]); if(rk)out(kth(i,rk)); else{pc(‘-‘);out(INF);}pc(\n);break; case 5:rk=rank(i,qk[i]+1); out(rk>qr[i]-ql[i]?INF:kth(i,rk+1));pc(\n); } } fwrite(obuf,1,po-obuf,stdout); return 0; }

洛谷P3380 【模板】二逼平衡樹(樹套樹,樹狀數組,線段樹)