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

输入输出样例

输入样例#1: 复制

5 10
59 46 14 87 41
0 2 1
0 1 1 14
0 1 1 57
0 1 1 88
4 2 4
0 2 5
0 2 4
4 2 1
2 2 2
1 1 5 91

输出样例#1: 复制

59
87
41
87
88
46

说明

数据规模:

对于30%的数据:1 \leq N, M \leq {10}^31≤N,M≤103

对于50%的数据:1 \leq N, M \leq {10}^41≤N,M≤104

对于70%的数据:1 \leq N, M \leq {10}^51≤N,M≤105

对于100%的数据:1 \leq N, M \leq {10}^6, 1 \leq {loc}_i \leq N, 0 \leq v_i < i, -{10}^9 \leq a_i, {value}_i \leq {10}^91≤N,M≤106,1≤loci​≤N,0≤vi​<i,−109≤ai​,valuei​≤109

经测试,正常常数的可持久化数组可以通过,请各位放心

数据略微凶残,请注意常数不要过大

另,此题I/O量较大,如果实在TLE请注意I/O优化

询问生成的版本是指你访问的那个版本的复制

样例说明:

一共11个版本,编号从0-10,依次为:

0 : 59 46 14 87 41

1 : 59 46 14 87 41

2 : 14 46 14 87 41

3 : 57 46 14 87 41

4 : 88 46 14 87 41

5 : 88 46 14 87 41

6 : 59 46 14 87 41

7 : 59 46 14 87 41

8 : 88 46 14 87 41

9 : 14 46 14 87 41

10 : 59 46 14 87 91

比较复杂 我也讲不明白 直接看代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e7 + 5;
int st[maxn], lch[maxn], rch[maxn], ans[maxn] = {1};
int n, m;
int tot = 0;
void init(){
	memset(st, 0, sizeof(st));
	memset(lch, 0, sizeof(lch));
	memset(rch, 0, sizeof(rch));
	tot = 0;
}
int build(int l, int r){
	int rt = ++tot;
	if(l == r){
		cin >> st[rt];
		return rt;
	}
	int mid = (l + r) >> 1;
	lch[rt] = build(l, mid);
	rch[rt] = build(mid + 1, r);
	return rt;
} 
int quetry(int num, int l, int r, int th){
	if(l == r) return st[num];
	int mid = (l + r) >> 1;
	if(th <= mid)
		return quetry(lch[num], l, mid, th);
	else
		return quetry(rch[num], mid + 1, r, th);
}
int update(int num, int l, int r, int th, int v){
 	int rt = ++tot;
 	if(l == r){
 		st[rt] = v;
 		return rt;
	}
	lch[rt] = lch[num];
	rch[rt] = rch[num];
	int mid = (l + r) >> 1;
	if(th <= mid)
	 	lch[rt] = update(lch[num], l, mid, th, v);
	else
		rch[rt] = update(rch[num], mid + 1, r, th, v);
 	return rt;
} 
int main(){
	ios::sync_with_stdio(false);
	init();
	while(cin >> n >> m){
	build(1, n);
	int ed, tp, th, u; 
	for(int i = 1; i <= m; i++){
		cin >> ed >> tp >> th;
		if(tp == 1) {
			cin >> u;
			ans[i] = update(ans[ed], 1, n, th, u);
		}
		if(tp == 2) {
			ans[i] = ans[ed];
			cout << quetry(ans[ed], 1, n, th) << endl;
		}
	}
}	
	return 0;
} 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值