题解:线段树模板题,线段树维护一个区间最小值和区间最大值。因为数组元素可能为负
所以答案一定是: max*max、 max*min、min*min中的最小值。
那么只要维护区间最小值的同时维护最大值,最后求最小值就好了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=200001;
int a[MAXN];
struct Tree
{
int l,r,s,k;
} nod[MAXN*4];
void creat (int t,int l,int r)
{
nod[t].l=l;
nod[t].r=r;
if(l==r)
{
nod[t].s=a[l];
nod[t].k=a[l];
return;
}
int m=(l+r)/2;
creat(t*2,l,m);
creat(t*2+1,m+1,r);
nod[t].s=min(nod[t*2].s,nod[t*2+1].s);
nod[t].k=max(nod[t*2].k,nod[t*2+1].k);
}
void update (int t,int n,int v)
{
if(nod[t].r==nod[t].l&&nod[t].r==n)
{
nod[t].s=v;
nod[t].k=v;
return;
}
int mid = (nod[t].l+nod[t].r)>>1;
if(n<=mid) update (t*2,n,v);
else update(2*t+1,n,v);
nod[t].s=min(nod[2*t].s,nod[2*t+1].s);
nod[t].k=max(nod[2*t].k,nod[2*t+1].k);
}
int query(int t,int l,int r,int flag)
{
if(l==nod[t].l&&r==nod[t].r)
{
if(flag) return nod[t].s;
else return nod[t].k;
}
int mid = (nod[t].l+nod[t].r)>>1;
if(r<=mid) return query(t*2,l,r,flag);
else if(l>mid) return query(2*t+1,l,r,flag);
else
{
if(flag) return min(query(2*t,l,mid,flag),query(t*2+1,mid+1,r,flag));
else return max(query(2*t,l,mid,flag),query(t*2+1,mid+1,r,flag));
}
}
int main()
{
int N;
cin>>N;
while(N--)
{
int n,m,i,x1,x2;
int s;
cin>>n;
int num=pow(2.0,n);
for(i=1; i<=num; i++)
scanf("%d",&a[i]);
creat(1,1,pow(2.0,n));
cin>>m;
while(m--)
{
scanf("%d%d%d",&s,&x1,&x2);
if(s==1)
{
int mini=query(1,x1+1,x2+1,1),maxi=query(1,x1+1,x2+1,0);
if(mini<0 && maxi<0) cout<<(ll)maxi*maxi<<endl;
else if(mini>0 && maxi>0) cout<<(ll)mini*mini<<endl;
else if(mini<0 && maxi>0) cout<<(ll)maxi*mini<<endl;
else if(maxi==0||mini==0) puts("0");
}
else update(1,x1+1,x2);
}
}
return 0;
}