2019.01.21 洛谷P3919 【模板】可持久化数组(主席树)

时间:2021-10-24 22:28:02

传送门

题意简述:支持在某个历史版本上修改某一个位置上的值,访问某个历史版本上的某一位置的值。


思路:

用主席树直接维护历史版本即可。

代码:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
inline int read(){
	int ans=0,w=1;
	char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans*w;
}
const int N=1e6+5;
int n,m,rt[N],a[N];
namespace SGT{
	#define lc (son[p][0])
	#define rc (son[p][1])
	#define mid (l+r>>1)
	int son[N*20][2],val[N*20],tot=0;
	inline void build(int&p,int l,int r){
		p=++tot;
		if(l==r){val[p]=a[l];return;}
		build(lc,l,mid),build(rc,mid+1,r);
	}
	inline void update(int&p,int o,int l,int r,int k,int v){
		p=++tot,lc=son[o][0],rc=son[o][1];
		if(l==r){val[p]=v;return;}
		k<=mid?update(lc,son[o][0],l,mid,k,v):update(rc,son[o][1],mid+1,r,k,v);
	}
	inline int query(int p,int l,int r,int k){
		if(l==r)return val[p];
		return k<=mid?query(lc,l,mid,k):query(rc,mid+1,r,k);
	}
}
int main(){
	n=read(),m=read();
	for(ri i=1;i<=n;++i)a[i]=read();
	SGT::build(rt[0],1,n);
	for(ri op,id,x,i=1;i<=m;++i){
		id=read(),op=read(),x=read(),rt[i]=rt[id];
		switch(op){
			case 1:SGT::update(rt[i],rt[id],1,n,x,read());break;
			default:cout<<SGT::query(rt[i],1,n,x)<<'\n';
		}
	}
	return 0;
}