我想要打一个主席树
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我想要打一个主席树相关的知识,希望对你有一定的参考价值。
这里提供了静态主席树及动态主席树(树状数组套主席树)的模板。
分别应用于静态区间第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;
}
思路好想码量巨大警告
以上是关于我想要打一个主席树的主要内容,如果未能解决你的问题,请参考以下文章