【模板】主席树

1.静态区间第k小

题解思路

对于每个位置维护一个线段树,显然每个线段树维护的信息可以加减
所以通过类似前缀和的思想求区间第k小

代码

#include <cstdio>
#include <algorithm>
#define ci const int
#define mid ((l+r)>>1)
ci Maxn=200010;
int n,m,N,l,r,k;
int a[Maxn],b[Maxn],T[Maxn];
struct Node {
	int cnt;
	int s[Maxn<<5],ls[Maxn<<5],rs[Maxn<<5];
	int build(ci& l,ci& r) {
		int rt=++cnt;
		if (l^r) ls[rt]=build(l,mid),rs[rt]=build(mid+1,r);
		return rt;
	}
	int modify(ci& pre,ci& l,ci& r,ci& x) {
		int rt=++cnt;
		s[rt]=s[pre]+1;ls[rt]=ls[pre];rs[rt]=rs[pre];
		if (l^r) x<=mid?ls[rt]=modify(ls[pre],l,mid,x):rs[rt]=modify(rs[pre],mid+1,r,x);
		return rt;
	}
	int query(ci& L,ci& R,ci& l,ci& r,ci& k) {
		if (l==r) return l;
		int xx=s[ls[R]]-s[ls[L]];
		return k<=xx?query(ls[L],ls[R],l,mid,k):query(rs[L],rs[R],mid+1,r,k-xx);
	}
}sgt;
int main() {
	scanf("%d%d",&n,&m);
	for (register int i=1;i<=n;++i) scanf("%d",&a[i]),b[i]=a[i];
	std::sort(b+1,b+n+1); N=std::unique(b+1,b+n+1)-b-1;
	T[0]=sgt.build(1,N);
	for (register int i=1;i<=n;++i) T[i]=sgt.modify(T[i-1],1,N,std::lower_bound(b+1,b+N+1,a[i])-b);
	for (register int i=1;i<=m;++i) {
		scanf("%d%d%d",&l,&r,&k);
		printf("%d\n",b[sgt.query(T[l-1],T[r],1,N,k)]);
	}
}

2.可持久化数组

题意简述

维护一个数组,支持查询或修改某一历史版本某一位置的值

代码

#include <cstdio>
#include <algorithm>
#define ci const int
#define mid ((l+r)>>1)
ci Maxn=1000010;
int n,m,pre,opt,loc,val;
int a[Maxn],T[Maxn];
struct Node {
	int cnt;
	int va[Maxn<<4],ls[Maxn<<4],rs[Maxn<<4];
	int build(ci& l,ci& r) {
		int rt=++cnt;
		if (l^r) ls[rt]=build(l,mid),rs[rt]=build(mid+1,r);
		else va[rt]=a[l];
		return rt;
	}
	int modify(ci& pre,ci& l,ci& r) {
		int rt=++cnt;
		va[rt]=va[pre];ls[rt]=ls[pre];rs[rt]=rs[pre];
		if (l^r) loc<=mid?ls[rt]=modify(ls[pre],l,mid):rs[rt]=modify(rs[pre],mid+1,r);
		else va[rt]=val;
		return rt;
	}
	int query(ci& edt,ci& l,ci& r) {
		if (l==r) return va[edt];
		return loc<=mid?query(ls[edt],l,mid):query(rs[edt],mid+1,r);
	}
}sgt;
int main() {
	scanf("%d%d",&n,&m);
	for (register int i=1;i<=n;++i) scanf("%d",&a[i]);
	T[0]=sgt.build(1,n);
	for (register int i=1;i<=m;++i) {
		scanf("%d%d%d",&pre,&opt,&loc);
		if (opt==1) scanf("%d",&val),T[i]=sgt.modify(T[pre],1,n);
		else printf("%d\n",sgt.query(T[pre],1,n)),T[i]=T[pre];
	}
}
posted @ 2019-08-04 14:16  xuyixuan  阅读(140)  评论(0编辑  收藏  举报