/*
hihocoder1586 线段树(裸)
实现一个数据结构,有如下操作:
1.询问[l,r]内ai*aj的最小值(i可以等于j)
2.修改某个点ai的值
17北京网络赛的题目,现场逗比写了四颗线段树分别维护正负数的最大最小值,两百行跪。
其实没有这么复杂,选择乘积的乘数时可以选同一个数,所以如果区间最小值为正,那么答案就是它的平方。
如果区间最小值为负,那么我们需要知道区间最大值。如果此时区间最大值为正,答案即为这两数的乘积。否则,为区间最大值的平方。
这个方法就是把模板打两遍。

至于用用节点保存每个区间最大最小正负值。。。。太复杂,尤其是要考虑区间内到底有没有正数或负数时。。。
写题前尽量先估算好难易程度,不要着急上手
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <cmath>
#include <algorithm>
#include <map>
#include <set>
#define ll long long 
#define fr(i,a,b) for(int i=a;i<=b;i++)
#define frr(i,a,b) for(int i=a;i>=b;i--)
#define ms(a,b) memset(a,b,sizeof(a))
#define scfd(a) scanf("%d",a)
#define scflf(a) scanf("%lf",a)
#define scfs(a) scanf("%s",a)
#define ptfd(a) printf("%d\n",a)
#define ptfs(a) printf("%s\n",a)
#define showd(a,b) printf(a"=%d\n",b)
#define showlf(a,b) printf(a"=%lf\n",b)
#define shows(a,b) printf(a"=%s\n",b)
#define mmcp(a,b) memcpy(a,b,sizeof(b))
#define pb(a) push_back(a)
using namespace std;
const int MAXN=200005;
const ll NEGINF=-999999ll;
const ll POSINF=999999ll;
ll stn_max[MAXN<<2],stn_min[MAXN<<2];
void push_up(int now){
    stn_max[now]=max(stn_max[now<<1],stn_max[1+(now<<1)]);
    stn_min[now]=min(stn_min[now<<1],stn_min[1+(now<<1)]);
}
void update(int now,int l,int r,int p,ll d){
    if(l==r-1){
       stn_max[now]=stn_min[now]=d; 
    }
    else{
        int mid=(l+r)/2;
        if(p<mid)
            update(now<<1,l,mid,p,d);
        else 
            update(1+(now<<1),mid,r,p,d);
        push_up(now);
    }
}
ll find_max(int now,int l,int r,int tl,int tr){
    if(l>=tl&&r<=tr)
        return stn_max[now];
    int mid=(l+r)/2;
    ll ans=NEGINF;

    if(tl<mid)
        ans=max(ans,find_max(now<<1,l,mid,tl,tr));
    if(tr>mid)
        ans=max(ans,find_max(1+(now<<1),mid,r,tl,tr));
    return ans;
}
ll find_min(int now,int l,int r,int tl,int tr){
    if(l>=tl&&r<=tr){
        return stn_min[now];
    }
    int mid=(l+r)/2;
    ll ans=POSINF;
    if(tl<mid)
        ans=min(ans,find_min(now<<1,l,mid,tl,tr));
    if(tr>mid)
        ans=min(ans,find_min((now<<1)+1,mid,r,tl,tr));
    return ans;
}
int cases,k;
void init(){
    fr(i,0,MAXN-1){
        stn_max[i]=NEGINF;
        stn_min[i]=POSINF;
    }
}
int main(){
    scfd(&cases);
    while(cases--){
        init();
        scfd(&k);
        int n=1<<k; 
        fr(i,0,n-1){
            ll t;
            scanf("%lld",&t);
            update(1,0,n,i,t);
        }
        int q;
        scfd(&q);
        while(q--){
            int md;ll a,b;
            scanf("%d%lld%lld",&md,&a,&b);
            if(md==2)
                update(1,0,n,(int)a,b);
            else{
                ll mx,mn;
                mx=find_max(1,0,n,(int)a,(int)b+1);
                mn=find_min(1,0,n,(int)a,(int)b+1);
                if(mn>=0)
                    printf("%lld\n",mn*mn);
                else{
                    if(mx>=0)
                       printf("%lld\n",mn*mx);
                    else 
                       printf("%lld\n",mx*mx);
                }
            }
        }

    }
    return 0;
}
 posted on 2017-09-27 16:28  cylcy  阅读(108)  评论(0编辑  收藏  举报