这里提供了静态主席树及动态主席树(树状数组套主席树)的模板。
分别应用于静态区间第k小及动态区间第k小。
静态:
#include<cstdio> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC target("avx") #pragma GCC optimize("Ofast") #pragma GCC optimize("inline") #pragma GCC optimize("-fgcse") #pragma GCC optimize("-fgcse-lm") #pragma GCC optimize("-fipa-sra") #pragma GCC optimize("-ftree-pre") #pragma GCC optimize("-ftree-vrp") #pragma GCC optimize("-fpeephole2") #pragma GCC optimize("-ffast-math") #pragma GCC optimize("-fsched-spec") #pragma GCC optimize("unroll-loops") #pragma GCC optimize("-falign-jumps") #pragma GCC optimize("-falign-loops") #pragma GCC optimize("-falign-labels") #pragma GCC optimize("-fdevirtualize") #pragma GCC optimize("-fcaller-saves") #pragma GCC optimize("-fcrossjumping") #pragma GCC optimize("-fthread-jumps") #pragma GCC optimize("-funroll-loops") #pragma GCC optimize("-fwhole-program") #pragma GCC optimize("-freorder-blocks") #pragma GCC optimize("-fschedule-insns") #pragma GCC optimize("inline-functions") #pragma GCC optimize("-ftree-tail-merge") #pragma GCC optimize("-fschedule-insns2") #pragma GCC optimize("-fstrict-aliasing") #pragma GCC optimize("-fstrict-overflow") #pragma GCC optimize("-falign-functions") #pragma GCC optimize("-fcse-skip-blocks") #pragma GCC optimize("-fcse-follow-jumps") #pragma GCC optimize("-fsched-interblock") #pragma GCC optimize("-fpartial-inlining") #pragma GCC optimize("no-stack-protector") #pragma GCC optimize("-freorder-functions") #pragma GCC optimize("-findirect-inlining") #pragma GCC optimize("-fhoist-adjacent-loads") #pragma GCC optimize("-frerun-cse-after-loop") #pragma GCC optimize("inline-small-functions") #pragma GCC optimize("-finline-small-functions") #pragma GCC optimize("-ftree-switch-conversion") #pragma GCC optimize("-foptimize-sibling-calls") #pragma GCC optimize("-fexpensive-optimizations") #pragma GCC optimize("-funsafe-loop-optimizations") #pragma GCC optimize("inline-functions-called-once") #pragma GCC optimize("-fdelete-null-pointer-checks") using namespace std; char *p1,*p2,buf[1<<20]; #define GC (p1==p2&&(p1=buf,p2=buf+fread(buf,1,1<<20,stdin),p1==p2)?0:(*(p1++))) //#define GC getchar() inline int in() { int ans; char t,k; while(((t=GC)!='-'&&(t>'9'||t<'0'))); k=(t=='-'); ans=k?0:(t-'0'); while((t=GC)>='0'&&t<='9')ans=ans*10+t-'0'; return k?-ans:ans; } const int maxn=100010; struct node{ int ls,rs; int sum; }; int root[maxn]; struct tree{ node t[maxn<<5]; int tot=0; inline void build(int &rt,int l,int r) { rt=++tot; t[rt].sum=0; if(l==r)return; int mid=((l+r)>>1); build(t[rt].ls,l,mid); build(t[rt].rs,mid+1,r); } int updata(int x,int p,int l,int r){ int rt=++tot; t[rt].ls=t[p].ls; t[rt].rs=t[p].rs; t[rt].sum=t[p].sum+1; if(l==r)return rt; int mid=((l+r)>>1); if(mid>=x)t[rt].ls=updata(x,t[rt].ls,l,mid); else t[rt].rs=updata(x,t[rt].rs,mid+1,r); return rt; } int gs(int x,int y,int l,int r,int k){ int mid=((l+r)>>1); int tmp=t[t[y].ls].sum-t[t[x].ls].sum; if(l==r)return l; if(k<=tmp)return gs(t[x].ls,t[y].ls,l,mid,k); else return gs(t[x].rs,t[y].rs,mid+1,r,k-tmp); } }tr; int n,m; int a[maxn],b[maxn]; int main() { n=in();m=in(); int i,j; for(i=1;i<=n;i++){ a[i]=in(); b[i]=a[i]; } sort(b+1,b+n+1); int bs=unique(b+1,b+n+1)-b-1; tr.build(root[0],1,bs); for(i=1;i<=n;i++) { int pos=lower_bound(b+1,b+bs+1,a[i])-b; root[i]=tr.updata(pos,root[i-1],1,bs); } for(i=1;i<=m;i++) { int l,r,k; l=in();r=in();k=in(); printf("%d\n",b[tr.gs(root[l-1],root[r],1,bs,k)]); } return 0; }
动态
注:动态的主席树空间一定要开大,不然RE调一天都调不出来
#include<cstdio> #include<iostream> #include<cstring> #include<cmath> #include<algorithm> using namespace std; inline int lowbit(int x){return x&(-x);} struct node{ int sum,ls,rs; }; const int maxn=500100; int n,m; int root1[maxn<<2]; int root[maxn<<2]; int a[maxn<<2],b[maxn<<2],bs; int tl[maxn<<2],tr[maxn<<2]; struct tree{ node sum[maxn<<6]; int tot=0; void pushup(int p) { sum[p].sum=sum[sum[p].ls].sum+sum[sum[p].rs].sum; } void build(int &p,int l,int r) { p=++tot; if(l==r)return; int mid=((l+r)>>1); build(sum[p].ls,l,mid); build(sum[p].rs,mid+1,r); // pushup(p); } int ins(int x,int p,int l,int r,int k) { int p1=++tot; sum[p1].ls=sum[p].ls; sum[p1].rs=sum[p].rs; sum[p1].sum=sum[p].sum+k; if(l==r){ return p1; } int mid=((l+r)>>1); if(x<=mid)sum[p1].ls=ins(x,sum[p].ls,l,mid,k); else sum[p1].rs=ins(x,sum[p].rs,mid+1,r,k); // pushup(p1); return p1; } void add(int x,int k) { int pos=lower_bound(b+1,b+bs+1,a[x])-b; while(x<=n){ root[x]=ins(pos,root[x],1,bs,k); x+=lowbit(x); } } int r_gs(int x,bool f) { int res=0; while(x){ if(f)res+=sum[sum[tr[x]].ls].sum; else res+=sum[sum[tl[x]].ls].sum; x-=lowbit(x); } return res; } int gs(int x,int y,int rx,int ry,int l,int r,int k) { if(l==r)return l; int mid=((l+r)>>1); int res=r_gs(y,1)-r_gs(x,0)+sum[sum[ry].ls].sum-sum[sum[rx].ls].sum; if(k<=res){ int i; for(i=y;i;i-=lowbit(i))tr[i]=sum[tr[i]].ls; for(i=x;i;i-=lowbit(i))tl[i]=sum[tl[i]].ls; return gs(x,y,sum[rx].ls,sum[ry].ls,l,mid,k); } else { int i; for(i=y;i;i-=lowbit(i))tr[i]=sum[tr[i]].rs; for(i=x;i;i-=lowbit(i))tl[i]=sum[tl[i]].rs; return gs(x,y,sum[rx].rs,sum[ry].rs,mid+1,r,k-res); } } }st; struct actt{ int x,y,k; bool ch; }g[maxn<<2]; int main() { int i,j; scanf("%d%d",&n,&m); for(i=1;i<=n;i++){ scanf("%d",&a[i]); b[i]=a[i]; bs+=1; } for(i=1;i<=m;i++) { char cc; cin>>cc>>g[i].x; if(cc=='Q')cin>>g[i].y>>g[i].k,g[i].ch=1; else cin>>g[i].y,b[++bs]=g[i].y; } sort(b+1,b+bs+1); int tmp=unique(b+1,b+bs+1)-b-1; bs=tmp; b[0]=-233; st.build(root1[0],1,bs); for(i=1;i<=n;i++)root1[i]=st.ins(lower_bound(b+1,b+bs+1,a[i])-b,root1[i-1],1,bs,1); for(i=1;i<=n;i++)root[i]=root1[0]; for(i=1;i<=m;i++) { if(g[i].ch){ for(j=g[i].y;j;j-=lowbit(j))tr[j]=root[j]; for(j=g[i].x-1;j;j-=lowbit(j))tl[j]=root[j]; printf("%d\n",b[st.gs(g[i].x-1,g[i].y,root1[g[i].x-1],root1[g[i].y],1,bs,g[i].k)]); } else{ st.add(g[i].x,-1); a[g[i].x]=g[i].y; st.add(g[i].x,1); } } return st.tot; }
思路好想码量巨大警告
来源:https://www.cnblogs.com/cooper233/p/12037924.html