主席树留坑
可持久化权值线段树:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<map>
#include<bitset>
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dwn(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
typedef long long ll;
const int N=200000;
int n,m,cnt,tot=0;
int a[N+10],b[N+10],rt[N+10];
int sum[100*N+10],tl[100*N+10],tr[100*N+10];
int read()
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<3)+(x<<1)+(ch^48);
ch=getchar();
}
return x*f;
}
int build(int l,int r)
{
int t=++tot;
sum[tot]=0;
if(l<r)
{
int mid=(l+r)>>1;
tl[t]=build(l,mid);
tr[t]=build(mid+1,r);
}
return t;
}
int update(int pre,int l,int r,int x)
{
int t=++tot;
tl[t]=tl[pre];tr[t]=tr[pre];sum[t]=sum[pre]+1;
if(l<r)
{
int mid=(l+r)>>1;
if(x<=mid) tl[t]=update(tl[pre],l,mid,x);
else tr[t]=update(tr[pre],mid+1,r,x);
}
return t;
}
int ask_sum(int u,int v,int l,int r,int k)
{
if(l>=r) return l;
int x=sum[tl[v]]-sum[tl[u]];
int mid=(l+r)>>1;
if(k<=x) return ask_sum(tl[u],tl[v],l,mid,k);
else return ask_sum(tr[u],tr[v],mid+1,r,k-x);
}
int main()
{
n=read(),m=read();
rep(i,1,n)
{
a[i]=b[i]=read();
}
sort(b+1,b+n+1);
cnt=unique(b+1,b+n+1)-b-1;
rt[0]=build(1,cnt);
rep(i,1,n)
{
int t=lower_bound(b+1,b+cnt+1,a[i])-b;
rt[i]=update(rt[i-1],1,cnt,t);
}
rep(i,1,m)
{
int l=read(),r=read(),k=read();
printf("%d
",b[ask_sum(rt[l-1],rt[r],1,cnt,k)]);
}
return 0;
}
可持久化数组-线段树实现:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<map>
#include<bitset>
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dwn(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
typedef long long ll;
const int N=1000000;
int n,m,a[N+10],rt[N+10],val[40*N+10],tl[40*N+10],tr[40*N+10],cnt=0,tot=0;
int read()
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<3)+(x<<1)+(ch^48);
ch=getchar();
}
return x*f;
}
int build(int l,int r)
{
int t=++tot;
if(l==r)
{
val[t]=a[l];
return t;
}
int mid=(l+r)>>1;
tl[t]=build(l,mid);
tr[t]=build(mid+1,r);
return t;
}
int update(int pre,int l,int r,int x,int d)
{
int t=++tot;
if(l==r)
{
val[t]=d;
return t;
}
tl[t]=tl[pre],tr[t]=tr[pre];
int mid=(l+r)>>1;
if(x<=mid) tl[t]=update(tl[pre],l,mid,x,d);
else tr[t]=update(tr[pre],mid+1,r,x,d);
return t;
}
int ask_val(int t,int l,int r,int x)
{
if(l==r) return val[t];
int mid=(l+r)>>1;
if(x<=mid) return ask_val(tl[t],l,mid,x);
else return ask_val(tr[t],mid+1,r,x);
}
int main()
{
n=read(),m=read();
rep(i,1,n) a[i]=read();
rt[0]=build(1,n);
rep(i,1,m)
{
int t=read(),opt=read(),x=read();
if(opt==1) {int d=read();rt[++cnt]=update(rt[t],1,n,x,d);}
if(opt==2) {printf("%d
",ask_val(rt[t],1,n,x));rt[++cnt]=rt[t];}
}
return 0;
}