You are given a list of integers a0, a1, …, a2^k-1.
You need to support two types of queries:
Output Minx,y∈[l,r] {ax∙ay}.
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 l r: Output Minx,y∈[l,r]{ax∙ay}. (0 ≤ l ≤ r < 2k)
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);
}
}
}