Minimum(2017 ACM/ICPC Asia Regional Beijing Online)

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.

Input

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)

Output

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

Sample Input

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

Sample Output

1
1
4

题意:

每次给出2^k个数,然后分别查询x,y∈[l,r]使得ax*ay最小,或者更新ax=y。

思路:

线段树的模版题。用线段树记录下区间的最大值和最小值,并且单点更新。
每次查询得到Min和Max,如果Min>0,那么ans=Min * Min;否则分两种情况,Max>0时,ans=Min * Max,否则ans=Max * Max。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <vector>
#include <iostream>
#include <string>
#include <map>
#include <stack>
#include <cstring>
#include <queue>
#include <list>
#include <stdio.h>
#include <set>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <iomanip>
#include <cctype>
#include <sstream>
#include <iterator>
#include <functional>
#include <stdlib.h>
#include <time.h>
#include <bitset>
using namespace std;

#define pi acos(-1)
#define s_1(x) scanf("%d",&x)
#define s_2(x,y) scanf("%d%d",&x,&y)
#define s_3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define s_4(x,y,z,X) scanf("%d%d%d%d",&x,&y,&z,&X)
#define s_5(x,y,z,X,Y) scanf("%d%d%d%d%d",&x,&y,&z,&X,&Y)
#define S_1(x) scan_d(x)
#define S_2(x,y) scan_d(x),scan_d(y)
#define S_3(x,y,z) scan_d(x),scan_d(y),scan_d(z)
#define PI acos(-1)
#define endl '\n'
#define srand() srand(time(0));
#define me(x,y) memset(x,y,sizeof(x));
#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
#define close() ios::sync_with_stdio(0); cin.tie(0);
#define FOR(x,n,i) for(int i=x;i<=n;i++)
#define FOr(x,n,i) for(int i=x;i<n;i++)
#define fOR(n,x,i) for(int i=n;i>=x;i--)
#define fOr(n,x,i) for(int i=n;i>x;i--)
#define W while
#define sgn(x) ((x) < 0 ? -1 : (x) > 0)
#define bug printf("***********\n");
#define db double
#define ll long long
#define mp make_pair
#define pb push_back

#define retrun return
#define ture true
typedef long long LL;
typedef pair <int, int> ii;
const int INF = 0x3f3f3f3f;
const LL LINF = 0x3f3f3f3f3f3f3f3fLL;
const int dx[] = {-1, 0, 1, 0, 1, -1, -1, 1};
const int dy[] = {0, 1, 0, -1, -1, 1, -1, 1};
const int maxn = (1 << 17) + 100;
const int maxx = 1e12 + 10;
const double EPS = 1e-8;
const double eps = 1e-10;
const int mod = 1e9 + 7;
const int MOD = 1e3;
template <class T> inline T min(T a, T b, T c) {return min(min(a, b), c);}
template <class T> inline T max(T a, T b, T c) {return max(max(a, b), c);}
template <class T> inline T min(T a, T b, T c, T d) {return min(min(a, b), min(c, d));}
template <class T> inline T max(T a, T b, T c, T d) {return max(max(a, b), max(c, d));}
template <class T> inline bool scan_d(T &ret) {
    char c;
    int sgn;
    if (c = getchar(), c == EOF) return 0;
    while (c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1 : 1;ret = (c == '-') ? 0 : (c - '0');
    while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return 1;
}
inline bool scan_lf(double &num) {
    char in;
    double Dec = 0.1;
    bool IsN = false, IsD = false;
    in = getchar();
    if (in == EOF) return false;
    while (in != '-' && in != '.' && (in < '0' || in > '9')) in=getchar();
    if (in == '-') {IsN = true; num = 0;}
    else if (in == '.') {IsD = true; num = 0;}
    else num = in - '0';
    if (!IsD) {
        while (in = getchar(), in >= '0' && in <= '9') {num *= 10; num += in - '0';}
    }
    if (in != '.') {
        if (IsN) num = -num;
        return true;
    }
    else{
        while (in = getchar(), in >= '0' && in <= '9') {
            num += Dec * (in - '0');
            Dec *= 0.1;
        }
    }
    if (IsN) num = num;
    return true;
}
void Out(LL a) {if(a < 0) {putchar('-'); a = -a;}if(a >= 10) Out(a / 10); putchar(a % 10 + '0');}
void print(LL a) {Out(a), puts("");}
/**********************************************WHITE_YASHA**********************************************/
//freopen( "in.txt" , "r" , stdin );
//freopen( "data.txt" , "w" , stdout );
//cerr << "run time is " << clock() << endl;
struct tree {
    int left, right, maxx, minn;
} T[maxn << 2];
int t, k, a, tmp, tmp_min, tmp_max;
void build(int x, int l, int r) {
    T[x].left = l;
    T[x].right = r;
    if (l == r) {
        scanf("%d", &tmp);
        T[x].maxx = T[x].minn = tmp;
        return ;
    }
    int m = (l + r) >> 1;
    build(x << 1, l, m);
    build(x << 1 | 1, m + 1, r);
    T[x].maxx = max(T[x << 1].maxx, T[x << 1 | 1].maxx);
    T[x].minn = min(T[x << 1].minn, T[x << 1 | 1].minn);
    //    printf("%d: %d %d %d %d\n", x, T[x].left, T[x].right, T[x].maxx, T[x].minn);
}
void update(int x, int p, int v) {
    if (T[x].left == p && T[x].right == p) {
        T[x].maxx = T[x].minn = v;
        return ;
    }
    int m = (T[x].left + T[x].right) >> 1;
    if (p <= m) update(x << 1, p, v);
    else update(x << 1 | 1, p, v);
    T[x].maxx = max(T[x << 1].maxx, T[x << 1 | 1].maxx);
    T[x].minn = min(T[x << 1].minn, T[x << 1 | 1].minn);
}
void query(int x, int l, int r) {
    if (T[x].left > r || T[x].right < l) return ;
    if (T[x].left == l && T[x].right == r) {
        tmp_max = max(tmp_max, T[x].maxx);
        tmp_min = min(tmp_min, T[x].minn);
        return ;
    }
    int m = (T[x].left + T[x].right) >> 1;
    if (m < l) query(x << 1 | 1, l, r);
    else if (m >= r) query(x << 1, l, r);
    else {
        query(x << 1, l, m);
        query(x << 1 | 1, m + 1, r);
    }
}
int main() {
    s_1(t);
    W (t--) {
        me(T, 0);
        s_1(k);
        build(1, 0, (1 << k) - 1);
//        printf("ok\n");
        s_1(a);
        int op, l, r;
        W (a--) {
            s_3(op, l, r);
            if (op == 1) {
                tmp_min = maxn;
                tmp_max = -maxn;
                query(1, l, r);
//                printf("%d %d\n", tmp_min, tmp_max);
                if (tmp_min < 0) {
                    if (tmp_max > 0) printf("%lld\n", 1ll * tmp_min * tmp_max);
                    else printf("%lld\n", 1ll * tmp_max * tmp_max);
                }
                else printf("%lld\n", 1ll * tmp_min * tmp_min);
            }
            else update(1, l, r);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值