1. 程式人生 > >ACM-ICPC國際大學生程序設計競賽北京賽區(2017)網絡賽 hihocoder #1586 : Minimum-區間查詢最值求區間兩數最小乘積+單點更新-線段樹(結構體版)

ACM-ICPC國際大學生程序設計競賽北京賽區(2017)網絡賽 hihocoder #1586 : Minimum-區間查詢最值求區間兩數最小乘積+單點更新-線段樹(結構體版)

ns2 edit AD memory body bmi json ffffff inf

#1586 : Minimum

Time Limit:1000ms Case Time Limit:1000ms Memory Limit:256MB

Description

You are given a list of integers a0, a1, …, a2^k-1.

You need to support two types of queries:

1. Output Minx,y∈[l,r] {ax?ay}.

2. Let ax=y.

Input

The first line is an integer T, indicating the number of test cases. (1≤T≤10).

For each test case:

The first line contains an integer k (0 ≤ k ≤ 17).

The following line contains 2k integers, a0, a1, …, a2^k-1 (-2k ≤ ai < 2k).

The next line contains a integer (1 ≤ Q < 2k), indicating the number of queries. Then next Q lines, each line is one of:

1. 1 l r: Output Minx,y∈[l,r]{ax?ay}. (0 ≤ l ≤ r < 2k)

2. 2 x y: Let ax=y. (0 ≤ x < 2k, -2k ≤ y < 2k)

Output

For each query 1, output a line contains an integer, indicating the answer.

Sample Input
1
3
1 1 2 2 1 1 2 2
5
1 0 7
1 1 2
2 1 2
2 2 2
1 1 2
Sample Output
1
1
4

這個題就是區間查詢最大值和最小值,通過判斷區間最大值和最小值的正負來得到區間最小乘積。

代碼:

 1 #include<iostream>
 2
#include<cstring> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<algorithm> 6 #include<cmath> 7 #include<queue> 8 #include<vector> 9 #define inf 0x7fffffff 10 #define lson l,m,rt<<1 11 typedef long long ll; 12 #define rson m+1,r,rt<<1|1 13 using namespace std; 14 const int maxn=1e6+10; 15 struct node{ 16 int left,right,maxx,minn; 17 }tree[maxn*4]; 18 int st_min[maxn<<2],st_max[maxn<<2]; 19 inline int minn(int a,int b){return a>b?b:a;} 20 inline int maxx(int a,int b){return a>b?a:b;} 21 void PushUP(int rt){ 22 st_min[rt]=minn(st_min[rt<<1],st_min[rt<<1|1]); 23 st_max[rt]=maxx(st_max[rt<<1],st_max[rt<<1|1]); 24 } 25 void build(int l,int r,int rt) { 26 if(l==r){ 27 scanf("%d",&st_min[rt]); 28 st_max[rt]=st_min[rt]; 29 return ; 30 } 31 int m=(l+r)>>1; 32 build(lson); 33 build(rson); 34 PushUP(rt); 35 } 36 void update(int p,int num,int l,int r,int rt){ 37 if(l==r){ 38 st_max[rt]=num; 39 st_min[rt]=num; 40 return ; 41 } 42 int m=(l+r)>>1; 43 if(p<=m)update(p,num,lson); 44 else update(p,num,rson); 45 PushUP(rt); 46 } 47 int query_min(int L,int R,int l,int r,int rt){ 48 if (L<=l&&r<=R){ 49 return st_min[rt]; 50 } 51 int m=(l+r)>>1; 52 int ret1=inf,ret2=inf; 53 if(L<=m)ret1=query_min(L,R,lson); 54 if(R>m) ret2=query_min(L,R,rson); 55 return minn(ret1,ret2); 56 } 57 int query_max(int L,int R,int l,int r,int rt){ 58 if(L<=l&&r<=R){ 59 return st_max[rt]; 60 } 61 int m=(l+r)>>1; 62 int ret1=-inf,ret2=-inf; 63 if(L<=m)ret1=query_max(L,R,lson); 64 if(R>m) ret2=query_max(L,R,rson); 65 return maxx(ret1,ret2); 66 } 67 int main(){ 68 int t; 69 scanf("%d",&t); 70 while(t--){ 71 int n,m; 72 scanf("%d",&n); 73 int k=pow(2,n); 74 build(1,k,1); 75 scanf("%d",&m); 76 while(m--){ 77 int h,a,b; 78 scanf("%d%d%d",&h,&a,&b); 79 if(h==2)update(a+1,b,1,k,1); 80 else{ 81 ll ans1=query_min(a+1,b+1,1,k,1); 82 ll ans2=query_max(a+1,b+1,1,k,1); 83 if(ans1<0&&ans2>=0) 84 printf("%lld\n",ans2*ans1); 85 else if(ans1<0&&ans2<0) 86 printf("%lld\n",ans2*ans2); 87 else 88 printf("%lld\n",ans1*ans1); 89 } 90 } 91 } 92 return 0; 93 }

ACM-ICPC國際大學生程序設計競賽北京賽區(2017)網絡賽 hihocoder #1586 : Minimum-區間查詢最值求區間兩數最小乘積+單點更新-線段樹(結構體版)