题目9 : Minimum
-
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
描述
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.
线段树,求个区间乘积的最小值。因为值可能是负数,所以要分情况讨论。
#include <cstdio>
#include <algorithm>
using namespace std;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int maxn = 200000;
int MAX[maxn << 2];
int MIN[maxn << 2];
int pos;
//区间最大值
void PushUP1(int rt) {
MAX[rt] = max(MAX[rt << 1], MAX[rt << 1 | 1]);
}
void build1(int l, int r, int rt) {
if (l == r) {
scanf("%d", &MAX[rt]);
MIN[rt] = MAX[rt];
return;
}
int m = (l + r) >> 1;
build1(lson);
build1(rson);
PushUP1(rt);
}
void update1(int p, int sc, int l, int r, int rt) {
if (l == r) {
MAX[rt] = sc;
return;
}
int m = (l + r) >> 1;
if (p <= m) update1(p, sc, lson);
else update1(p, sc, rson);
PushUP1(rt);
}
int query1(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) {
return MAX[rt];
}
int m = (l + r) >> 1;
int ret = -maxn;
if (L <= m) ret = max(ret, query1(L, R, lson));
if (R > m) ret = max(ret, query1(L, R, rson));
return ret;
}
//区间最小值
void PushUP2(int rt) {
MIN[rt] = min(MIN[rt << 1], MIN[rt << 1 | 1]);
}
void build2(int l, int r, int rt) {
if (l == r) {
return;
}
int m = (l + r) >> 1;
build2(lson);
build2(rson);
PushUP2(rt);
}
void update2(int p, int sc, int l, int r, int rt) {
if (l == r) {
MIN[rt] = sc;
return;
}
int m = (l + r) >> 1;
if (p <= m) update2(p, sc, lson);
else update2(p, sc, rson);
PushUP2(rt);
}
int query2(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) {
return MIN[rt];
}
int m = (l + r) >> 1;
int ret = maxn;
if (L <= m) ret = min(ret, query2(L, R, lson));
if (R > m) ret = min(ret, query2(L, R, rson));
return ret;
}
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
pos = 1;
int k;
scanf("%d", &k);
//节点个数
for (int i = 0; i < k; i++)
{
pos *= 2;
}
build1(1, pos, 1);
build2(1, pos, 1);
int q;
scanf("%d", &q);
while (q--)
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
if (a == 2)
{//更新
update1(b + 1, c, 1, pos, 1);
update2(b + 1, c, 1, pos, 1);
}
if (a == 1)
{
long long min1 = query2(b + 1, c + 1, 1, pos, 1);
long long max1 = query1(b + 1, c + 1, 1, pos, 1);
long long ans;
if (min1 <= 0&&max1>=0)//最小负数乘最大正数最小
{
ans = min1*max1;
}
else if (min1 > 0)//最小正数乘最小正数最小
{
ans = min1*min1;
}
else if ( max1 < 0)//最大负数乘最大负数最小
{
ans = max1*max1;
}
printf("%lld\n", ans);
}
}
}
return 0;
}