主席树题目整理

前话:由于太菜,所以开个坑整理有关主席树的题目,可能会咕咕咕。

1.P3834 【模板】可持久化线段树 2(主席树)

区间第 k k k小,转权值主席树,具体见代码。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e6+5,M=N*21,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
template<class T>
inline void read(T &x){ 
	x=0;int w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
	for(;ch>='0'&&ch<='9';ch=getchar())
		x=(x<<3)+(x<<1)+(ch&15);
	x*=w; 
}
int a[N],rt[M],b[N];
struct PST{
	int lx[M],rx[M],s[M],cnt;
	void build(int &x,int l,int r){	//建树 
		x=++cnt;
		if(l==r){return;}	
		int mid=(l+r)>>1;
		build(lx[x],l,mid),build(rx[x],mid+1,r);
	}
	void upd(int &x,int pre,int l,int r,int v){	//更新 
		x=++cnt,lx[x]=lx[pre],rx[x]=rx[pre],s[x]=s[pre]+1; 
		if(l==r){return;}
		int mid=(l+r)>>1;
		if(v<=mid) upd(lx[x],lx[pre],l,mid,v);
		else upd(rx[x],rx[pre],mid+1,r,v);
	}
	int query(int l,int r,int u,int v,int k){	//查询. 
		if(l>=r) return l;
		int cnt=s[lx[v]]-s[lx[u]];
		int mid=(l+r)>>1;
		if(cnt>=k) return query(l,mid,lx[u],lx[v],k);
		else return query(mid+1,r,rx[u],rx[v],k-cnt);
	}
}T;
int main(){
	int n,m;
	read(n),read(m);
	for(reg int i=1;i<=n;i++)
		read(a[i]),b[i]=a[i];
	sort(b+1,b+n+1);	//离散化. 
	int cnt=unique(b+1,b+n+1)-b-1;
	T.build(rt[0],1,cnt);
	for(reg int i=1;i<=n;i++){
		int p=lower_bound(b+1,b+cnt+1,a[i])-b;
		T.upd(rt[i],rt[i-1],1,cnt,p);
	}
	while(m--){
		int l,r,k;
		read(l),read(r),read(k);
		int id=T.query(1,cnt,rt[l-1],rt[r],k);
		printf("%d\n",b[id]);
	}
	return 0;
}