1. 程式人生 > >ACM-ICPC國際大學生程序設計競賽北京賽區(2017)網絡賽 i題 Minimum(線段樹)

ACM-ICPC國際大學生程序設計競賽北京賽區(2017)網絡賽 i題 Minimum(線段樹)

hellip each pri ger out ont amp define void

描述

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.

輸入

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)

輸出

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

樣例輸入

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

樣例輸出

1
1
4

解題思路:
之前沒看到有負號和可以相等,想復雜了,zz,其實很簡單,要想區間內兩個數的乘積最小,那麽當區間最大值max>=0,區間最小值min>=0時,最小的不就是min的平方(因為可以相
等),當max<0,min<0時, 最小的就是max*max了,當max>0.min<0時最小的就是min*max.
實現代碼:
#include <cstdio>
#include <cstring>
#include<iostream>
#include<cmath>
#define  inf 0x7fffffff
#define lson l , m , rt << 1
#define ll long long
#define rson m + 1 , r , rt << 1 | 1
using namespace std;
const int maxn = 1000001;


int st_min[maxn<<2],st_max[maxn<<2];

inline int minn(int a,int b) { return a>b?b:a; }
inline int maxx(int a,int b) { return a>b?a:b; }
void PushUP(int rt)
{
    st_min[rt] = minn(st_min[rt<<1],st_min[rt<<1|1]);
    st_max[rt] = maxx(st_max[rt<<1],st_max[rt<<1|1]);
}
void build(int l,int r,int rt) {
    if (l == r)
    {
        scanf("%d",&st_min[rt]);
        st_max[rt] = st_min[rt];
        return ;
    }
    int m = (l + r) >> 1;
    build(lson);
    build(rson);
    PushUP(rt);
}

int query_min(int L,int R,int l,int r,int rt)
{
    if (L <= l && r <= R) {
        return st_min[rt];
    }
    int m = (l + r) >> 1;
    int ret1 = inf,ret2 = inf;
    if (L <= m) ret1 = query_min(L , R , lson);
    if (R > m) ret2 = query_min(L , R , rson);
    return minn(ret1,ret2);
}
void update(int p,int num,int l,int r,int rt) {
       if (l == r) {
              st_max[rt] = num;
              st_min[rt] = num;
              return ;
       }
       int m = (l + r) >> 1;
       if (p <= m) update(p , num , lson);
       else update(p , num , rson);
       PushUP(rt);
}
int query_max(int L,int R,int l,int r,int rt)
{
    if (L <= l && r <= R) {
        return st_max[rt];
    }
    int m = (l + r) >> 1;
    int ret1 = -inf,ret2 = -inf;
    if (L <= m) ret1 = query_max(L , R , lson);
    if (R > m) ret2 = query_max(L , R , rson);
    return maxx(ret1,ret2);
}

int main()
{
     int n,m,t,i,k,x,y,z,ms;
     for(i=0;i<4;i++)
         ms++;
     long long sum;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&k);
        int n = pow(2,k);
        build(1,n,1);
        scanf("%d",&m);
        while(m--){
            scanf("%d%d%d",&x,&y,&z);
            if(x==2){
                y+=1;
                update(y,z,1,n,1);
            }
            else{
                y+=1;z+=1;
                ll ans1 = query_min(y,z,1,n,1);
                ll ans2 = query_max(y,z,1,n,1);
                if(ans1<0&&ans2>=0){
                 sum = ans1*ans2;
                 printf("%lld\n",sum);
                }
                else if(ans1<0&&ans2<0){
                sum = ans2 * ans2;
                cout<<sum<<endl;
               }
                else{
                    sum = ans1*ans1;
                    printf("%lld\n",sum);
                }
            }
        }
    }
    return 0;
}

ACM-ICPC國際大學生程序設計競賽北京賽區(2017)網絡賽 i題 Minimum(線段樹)