【9018:2207】可持久化線段樹1
阿新 • • 發佈:2018-03-08
正整數 page sta 輸出 amp status efi oid 所有
提交: 45 解決: 14
[提交][狀態][討論版]
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