洛谷P3919 【模板】可持久化数组(可持久化线段树/平衡树)

主席树太费空间了,而本题也无需维护任何区间信息,只是查询历史版本点值,没必要构造可持久化线段树,我们可以构建结构类似于 BST 的可持久化数据结构,这样每个非叶节点也会带有权值,不会被浪费掉
Code;

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 1000000 + 3;
int n, m, root[maxn], ls[maxn * 51], rs[maxn * 51], cnt_node;
long long  A[maxn], val[maxn * 51];
struct Segment_Tree
{
	void build(int l,int r,int &o){
		if(l > r) return ;
		o = ++cnt_node;
		int mid = (l + r) >> 1;
		val[o] = A[mid];
		build(l, mid - 1, ls[o]);
		build(mid + 1, r, rs[o]);
	}
	int update(int l, int r, int k, long long  delta,  int o)
	{
		int oo = ++cnt_node;
		val[oo] = val[o];
		ls[oo] = ls[o];
		rs[oo] = rs[o];
		int mid = (l + r) >> 1;
		if(k == mid) { val[oo] = delta;  return oo;}
		if(k <= mid - 1) ls[oo] = update(l, mid - 1, k, delta, ls[o]);
		else rs[oo] = update(mid + 1, r, k, delta, rs[o]);
		return oo;
	}
	long long  query(int l,int r,int pos,int o)
	{
		int mid = (l + r) >> 1;
		if(mid == pos) return val[o];
		else if(mid - 1 >= pos) return query(l, mid - 1, pos, ls[o]);
		else return query(mid + 1, r, pos , rs[o]);
	}
}T;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n; ++i) scanf("%lld",&A[i]);
    T.build(1, n, root[0]);
    for(int i = 1;i <= m; ++i)
    {
    	int pre, opt, pos, v;
    	scanf("%d%d%d",&pre, &opt, &pos);
    	switch(opt)
    	{
    		case 1:
    		{
    			scanf("%d",&v);
    			root[i] = T.update(1, n, pos, v, root[pre]);
    			break;
    		}
    		case 2:
    		{
    			root[i] = root[pre];
    			printf("%lld
", T.query(1, n, pos, root[i]));
    			break;
    		}
    	}
    }

    return 0;
}

  

原文地址:https://www.cnblogs.com/guangheli/p/9845078.html