主席树模板二:【洛谷 P3919】可持久化线段树 1(可持久化数组)

【洛谷 P3919】可持久化线段树 1(可持久化数组)

题目大意:

让你维护一个数组,维护两个操作:
1.在数组的某个历史版本上修改一个数,修改后生成一个新的版本。
2 查询数组某个历史版本上的某个位置上数的值,将该版本拷贝一份作为新的版本。

思路:

主席树的模板。
关于主席树
建主席树,询问,修改。
每次在树中找到该历史版本,直接修改。
询问时将该历史版本复制即可。

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#include<vector>
#define r register
#define rep(i,x,y) for(r ll i=x;i<=y;++i)
#define per(i,x,y) for(r ll i=x;i>=y;--i)
using namespace std;
typedef long long ll;
const ll V=1e6+10;
ll tree[V<<5],a[V];
ll lc[V<<5],rc[V<<5],x,y,k,t;
ll n,m,top,cnt,f[V<<5],ans,opt;
void build(ll &now,ll x,ll y)
{
    now=++cnt;
    if(x==y) 
	{
		tree[now]=a[x];
		return;
	}
    ll mid=x+y>>1;
    build(lc[now],x,mid);
    build(rc[now],mid+1,y);
}
void add(ll &now,ll pre,ll x,ll y,ll val,ll p)
{
	now=++cnt;
	lc[now]=lc[pre],rc[now]=rc[pre];
	tree[now]=tree[pre];
	if(x==y)
	{
		tree[now]=val;
		return ;
	}
	ll mid=x+y>>1;
	if(p<=mid) add(lc[now],lc[pre],x,mid,val,p);
	else add(rc[now],rc[pre],mid+1,y,val,p);
}
ll ask(ll now,ll x,ll y,ll k)
{
	if(x==y) return tree[now];
	ll mid=x+y>>1;
	if(k<=mid) return ask(lc[now],x,mid,k);
	else return ask(rc[now],mid+1,y,k);
}
int main()
{
	scanf("%lld%lld",&n,&m);
	rep(i,1,n) 
	 scanf("%lld",&a[i]);
	build(f[0],1,n);			
	rep(i,1,m)
	{
		scanf("%lld%lld%lld",&t,&opt,&x);
		if(opt==1)
		{
			scanf("%lld",&k);
			add(f[i],f[t],1,n,k,x);
		}
		else 
		{
			printf("%lld\n",ask(f[t],1,n,x));
			f[i]=f[t];
		}
		
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值