hihocoder1586-2017acm北京网络赛9&线段树&思维&板子- Minimum

http://hihocoder.com/problemset/problem/1586
线段树,单点更新,区间查询极值。
给你一个数组,
有下面操作
输入 a b c
若为1,那么再b-c中找两个数,让他们的乘积最小。
若为2,那么把 a[b]=c;
乘积最小这个。。
因为有正负数。所以需要
min*min1 max1*max1 max1*min1 的最小值。。。

#include 
using namespace std;
typedef long long  ll;
/*
  。。值就是 min*max
     min*min 和max*max这么中间的最小值。。
  线段树,总结一下板子把。。
  这个结论没有想到。。
*/
const int maxn=1e6;
ll mins[maxn*4];
ll maxs[maxn*4];
const int inf=1e5;
void build(ll id,ll l,ll r)
{
    ll m;
    if(l==r)
    {
        scanf("%lld",&maxs[id]);
        mins[id]=maxs[id];
        return ;
    }
        m=(l+r)/2;
        build(id<<1,l,m);
        build((id<<1)+1,m+1,r);
        maxs[id]=max(maxs[id*2],maxs[id*2+1]);
        mins[id]=min(mins[id*2],mins[id*2+1]);
}
ll query(ll id,ll l,ll r,ll L, ll R)
{
    ll ret=-inf;
    if(l<=L && r>=R)
        return maxs[id];
    ll m=(L+R)/2;
    if(l<=m)
        ret=max(ret,query(id<<1,l,r,L,m));
    if(r>m)
        ret=max(ret,query((id<<1)+1,l,r,m+1,R));
    return ret;
}
ll query1(ll id,ll l,ll r,ll L, ll R)
{
    ll ret=inf;
    if(l<=L && r>=R){
            //cout<
        return mins[id];}
    ll m=(L+R)/2;
    if(l<=m)
        ret=min(ret,query1(id<<1,l,r,L,m));
    if(r>m)
        ret=min(ret,query1((id<<1)+1,l,r,m+1,R));
    return ret;
}
void update(ll x,ll y,ll l,ll r,ll id)
{
    if(l==r)
    {
        maxs[id]=y;
        mins[id]=y;
        return ;
    }
    ll m=(l+r)/2;
    if(x<=m)
        update(x,y,l,m,id*2);
    else
        update(x,y,m+1,r,id*2+1);
    maxs[id]=max(maxs[id*2],maxs[id*2+1]);
    mins[id]=min(mins[id*2],mins[id*2+1]);
}
int main()
{  ll t,m,n,a,b,c;
    scanf("%lld",&t);
    while(t--){
          scanf("%lld",&m);
           m=(int)pow(2,m);
          build(1,1,m);
          scanf("%lld",&n);
          for(int i=0;i"%lld%lld%lld",&a,&b,&c);
              if(a==1){
                  b++;c++;
                  //cout<
                  ll ans1=query(1,b,c,1,m);
                  ll ans2=query1(1,b,c,1,m);
                  //cout<
                  ll all=min(ans1*ans1,ans2*ans2);
                  all=min(all,ans1*ans2);
                  printf("%lld\n",all);
              }
              else{
                 update(b+1,c,1,m,1);
              }
          }
    }
    return 0;
}

你可能感兴趣的:(线段树)