【9018:2207】可持久化线段树1

2207: 【模板】可持久化线段树1

时间限制: 2 Sec 内存限制: 256 MB
提交: 45 解决: 14
[提交][状态][讨论版]

题目描述

你需要维护1个数列的若干版本:

对于给定的数列:a1...an

存在如下两种操作:

1.在vi版本的基础上,修改ax为val

2.查询第vi版本的[l,r]内的最小值。

注:

版本i表示为第i次操作后的数列情况,即改动不影响过去。

版本0为初始版本,若操作为查询,则直接复制一次数列作为当前版本。

输入

第1行2个正整数n,m表示数列长度以及操作次数

第2行n个整数表示初始序列ai

接下来m行,每行格式为vi opti xi yi

表示在vi版本的基础上,执行操作opti

若opti = 1 ,表示修改axi 为 yi(保证1<=xi<=n)

若opti = 2 ,表示查询[xi,yi]内的最小值(保证1<=xi<=yi<=n)

输出

对于所有opti=2的操作

输出1行表示答案。

样例输入

5 10
1 2 3 4 5
0 2 1 3
1 1 2 6
1 1 3 0
3 2 2 5
3 2 1 3
2 1 1 8
6 2 1 3
7 2 1 2
0 1 3 5
9 2 2 5

样例输出

1
0
0
3
6
2

提示

1<=n,m<=5*10^5

0<=vi<i

1<=opti<=2

|xi|,|yi|<=10^9

代码如下:

 1 #include<cstdio>
 2 #include<iostream>
 3 #define MN 500005
 4 #define MM 20000005
 5 using namespace std;
 6 int n,q,v[MN],rt[MN],cnt,T[MM],ls[MM],rs[MM];
 7 void build(int &k,int l,int r){
 8     if(!k) k=++cnt;
 9     if(l==r){T[k]=v[l];return;}
10     int mid=(l+r)>>1;
11     build(ls[k],l,mid); build(rs[k],mid+1,r);
12     T[k]=min(T[ls[k]],T[rs[k]]);
13 }
14 void update(int &k,int l,int r,int v,int ad){
15     ls[++cnt]=ls[k],rs[cnt]=rs[k],k=cnt;
16     if(l==r){T[k]=ad;return;}
17     int mid=(l+r)>>1;
18     if(v<=mid) update(ls[k],l,mid,v,ad);
19     else update(rs[k],mid+1,r,v,ad);
20     T[k]=min(T[ls[k]],T[rs[k]]);
21 }
22 int query(int k,int l,int r,int a,int b){
23     if(l==a&&r==b) return T[k];
24     int mid=(l+r)>>1;
25     if(b<=mid) return query(ls[k],l,mid,a,b);
26     if(a>mid) return query(rs[k],mid+1,r,a,b);
27     return min(query(ls[k],l,mid,a,mid),query(rs[k],mid+1,r,mid+1,b));
28 }
29 int main()
30 {
31     scanf("%d%d",&n,&q);
32     for(int i=1;i<=n;i++) scanf("%d",&v[i]);
33     build(rt[0],1,n);
34     for(int i=1;i<=q;i++){
35         int lst,opt,x,y;
36         scanf("%d%d%d%d",&lst,&opt,&x,&y);
37         rt[i]=rt[lst];
38         if(opt==1) update(rt[i],1,n,x,y);
39         else printf("%d
",query(rt[i],1,n,x,y));
40     }
41     return 0;
42 }
原文地址:https://www.cnblogs.com/Beginner-/p/8529043.html