1. 程式人生 > >【9018:2207】可持久化線段樹1

【9018:2207】可持久化線段樹1

正整數 page sta 輸出 amp status efi oid 所有

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\n",query(rt[i],1,n,x,y)); 40 } 41 return 0; 42 }

【9018:2207】可持久化線段樹1