#1586 : 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.
题意:给出一个数组,有多次查询,查询类型1 : 问区间(l,r)里找两个数使乘积最小,(可以重复使用数字)
查询类型2:把下标为 x 的值该为 c
思路:用线段树维护一个区间的最大值和最小值,查询答案的时候定位到这个区间,然后根据最大值和最小值的正负找到最小的组合,输出答案即可
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define ll long long
#define maxn 500005
struct Tree{
int minn,maxx,l,r;
}tree[maxn * 4];
int arr[maxn * 4];
void push_up(int i){
tree[i].maxx = max(tree[i << 1].maxx,tree[i << 1 | 1].maxx);
tree[i].minn = min(tree[i << 1].minn,tree[i << 1 | 1].minn);
}
void build(int l,int r,int i){
tree[i].l = l;
tree[i].r = r;
int mid = (l + r) >> 1;
if(l == r){
tree[i].maxx = tree[i].minn = arr[l];
}else{
build(l,mid,i << 1);
build(mid + 1,r,i << 1 | 1);
push_up(i);
}
}
void update(int x,int c,int i){
if(tree[i].l == x && tree[i].r == x){
tree[i].maxx = tree[i].minn = c;
return ;
}
int mid = (tree[i].l + tree[i].r) >> 1;
if(mid >= x)
update(x,c,i << 1);
else if(mid < x){
update(x,c,i << 1 | 1);
}else{
update(x,c,i << 1);
update(x,c,i << 1 | 1);
}
push_up(i);
}
Tree query(int x,int y,int i){
if(x <= tree[i].l && tree[i].r <= y){
return tree[i];
}
int mid = (tree[i].l + tree[i].r) >> 1;
if(mid >= y){
return query(x,y,i << 1);
}else if(mid < x){
return query(x,y,i << 1 | 1);
}else{
Tree t1,t2,tmp;
t1 = query(x,y,i << 1);
t2 = query(x,y,i << 1 | 1);
tmp.maxx = max(t1.maxx,t2.maxx);
tmp.minn = min(t1.minn,t2.minn);
return tmp;
}
}
int main(){
int n,m,a,b,c,t;
ll ans;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
n = 1 << n;
for(int i = 1;i <= n;i++){
scanf("%d",&arr[i]);
}
build(1,n,1);
scanf("%d",&m);
while(m--){
scanf("%d %d %d",&a,&b,&c);
if(a == 1){
Tree tmp = query(b + 1,c + 1,1);
if(tmp.minn <= 0 && tmp.maxx >= 0){
ans = (ll)tmp.maxx * tmp.minn;
}else if(tmp.minn < 0 && tmp.maxx <= 0)
ans = (ll)tmp.maxx * tmp.maxx;
else
ans = (ll)tmp.minn * tmp.minn;
printf("%lld\n",ans);
}else{
update(b + 1,c,1);
}
}
}
return 0;
}