https://hihocoder.com/problemset/problem/1586
线段树操作,原来题并不难。。。。。
要求乘积最小只要求区间内最大值、最小值和绝对值小的数,再判断min,max正负就行了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #define lson l,m,rt<<1 7 #define rson m+1,r,rt<<1|1 8 using namespace std; 9 typedef long long ll; 10 const int maxn=(1<<17)+2000; 11 int Max[maxn<<2],Min[maxn<<2],Mid[maxn<<2]; 12 13 int mid(int a,int b) 14 { 15 if(abs(a)<abs(b)) return a; 16 else return b; 17 } 18 19 void PushUpMax(int rt) 20 { 21 Max[rt]=max(Max[rt<<1],Max[rt<<1|1]); 22 } 23 24 void PushUpMin(int rt) 25 { 26 Min[rt]=min(Min[rt<<1],Min[rt<<1|1]); 27 } 28 29 void PushUpMid(int rt) 30 { 31 Mid[rt]=mid(Mid[rt<<1],Mid[rt<<1|1]); 32 } 33 34 35 void Build(int l,int r,int rt) 36 { 37 if(l==r){ 38 scanf("%d",&Max[rt]); 39 Min[rt]=Mid[rt]=Max[rt]; 40 return; 41 } 42 int m=(l+r)>>1; 43 Build(lson); 44 Build(rson); 45 PushUpMax(rt); 46 PushUpMin(rt); 47 PushUpMid(rt); 48 } 49 50 void Update(int pos,int val,int l,int r,int rt) 51 { 52 if(l==r){ 53 Mid[rt]=Min[rt]=Max[rt]=val; 54 return; 55 } 56 int m=(l+r)>>1; 57 if(pos<=m) Update(pos,val,lson); 58 else Update(pos,val,rson); 59 PushUpMax(rt); 60 PushUpMin(rt); 61 PushUpMid(rt); 62 } 63 64 int QueryMax(int L,int R,int l,int r,int rt) 65 { 66 if(L<=l&&r<=R){ 67 return Max[rt]; 68 } 69 int m=(l+r)>>1; 70 int res=-maxn-5000; 71 if(L<=m) res=max(res,QueryMax(L,R,lson)); 72 if(R>m) res=max(res,QueryMax(L,R,rson)); 73 return res; 74 } 75 76 int QueryMin(int L,int R,int l,int r,int rt) 77 { 78 if(L<=l&&r<=R){ 79 return Min[rt]; 80 } 81 int m=(l+r)>>1; 82 int res=maxn+5000; 83 if(L<=m) res=min(res,QueryMin(L,R,lson)); 84 if(R>m) res=min(res,QueryMin(L,R,rson)); 85 return res; 86 } 87 88 int QueryMid(int L,int R,int l,int r,int rt) 89 { 90 if(L<=l&&r<=R){ 91 return Mid[rt]; 92 } 93 int m=(l+r)>>1; 94 int res=maxn; 95 if(L<=m) res=mid(res,QueryMid(L,R,lson)); 96 if(R>m) res=mid(res,QueryMid(L,R,rson)); 97 return res; 98 } 99 100 int main() 101 { 102 int T,n,m,k,a,b; 103 scanf("%d",&T); 104 while(T--) 105 { 106 scanf("%d",&n); 107 n=1<<n; 108 Build(1,n,1); 109 scanf("%d",&m); 110 while(m--) 111 { 112 scanf("%d%d%d",&k,&a,&b); 113 a++; 114 if(k==1){ 115 b++; 116 ll t1=(ll)QueryMax(a,b,1,n,1); 117 ll t2=(ll)QueryMin(a,b,1,n,1); 118 ll t3=(ll)QueryMid(a,b,1,n,1); 119 if((t1>=0)&&(t2<=0)) 120 printf("%lld\n",t1*t2); 121 else if(t1<0||t2>0) 122 printf("%lld\n",t3*t3); 123 } 124 else Update(a,b,1,n,1); 125 } 126 } 127 return 0; 128 }
时间: 2024-10-25 21:31:44