题目9 : Minimum
时间限制:1000ms
单点时限:1000ms
内存限制:256MB
描述
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
时间限制:1000ms
单点时限:1000ms
内存限制:256MB
描述
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
题意:给你n个数,执行2中操作,操作一是查询数组下标在[l.r]区间内两数乘积的最小值(两个数可以选择同一个数),操作二是将ax改为y。用线段树维护一个区间最大值和区间最小值,然后分情况讨论:如果二者都大于0,则答案是最小值的平方,如果都小于0,答案是最大值的平方,否则答案是最大值乘以最小值。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#define L(u) (u<<1)
#define R(u) (u<<1|1)
using namespace std;
typedef long long ll;
const int maxn = 140005;
int a[maxn];
struct Node {
int l,r;
int _max,_min;
} node[maxn<<2];
void Pushup(int u) { //向上延时更新
node[u]._max=max(node[L(u)]._max,node[R(u)]._max);
node[u]._min=min(node[L(u)]._min,node[R(u)]._min);
return;
}
void Build(int u,int left,int right) { //建树
node[u].l=left;
node[u].r=right;
if(node[u].l==node[u].r) {
node[u]._max=node[u]._min=a[left];
return;
}
int mid=(node[u].l+node[u].r)>>1;
Build(L(u),left,mid);
Build(R(u),mid+1,right);
Pushup(u);
}
void Update(int u,int pos,int val) { //更新结点
if(node[u].l==node[u].r) {
node[u]._max=node[u]._min=val;
return;
}
int mid=(node[u].l+node[u].r)>>1;
if(pos<=mid) Update(L(u),pos,val);
else Update(R(u),pos,val);
Pushup(u);
}
int Quary1(int u,int left,int right) { //区间查询最大值
if(left==node[u].l&&right==node[u].r) {
return node[u]._max;
}
int mid=(node[u].l+node[u].r)>>1;
if(right<=mid) return Quary1(L(u),left,right);
else if(left>mid) return Quary1(R(u),left,right);
else return max(Quary1(L(u),left,mid),Quary1(R(u),mid+1,right));
}
ll Quary2(int u,int left,int right) { //区间查询最小值
if(left==node[u].l&&right==node[u].r) {
return node[u]._min;
}
int mid=(node[u].l+node[u].r)>>1;
if(right<=mid) return Quary2(L(u),left,right);
else if(left>mid) return Quary2(R(u),left,right);
else return min(Quary2(L(u),left,mid),Quary2(R(u),mid+1,right));
}
int main () {
//freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--) {
int n,p,x,y,q;
scanf("%d",&n);
for(int i=1; i<=(1<<n); i++)
scanf("%d",&a[i]);
Build(1,1,1<<n);
scanf("%d",&q);
while(q--) {
ll _max,_min;
scanf("%d%d%d",&p,&x,&y);
if(p==1) {
_max=Quary1(1,x+1,y+1);
_min=Quary2(1,x+1,y+1);
if(_max>=0&&_min>=0) printf("%lld\n",_min*_min);
else if(_max<=0&&_min<=0) printf("%lld\n",_max*_max);
else printf("%lld\n",_max*_min);
} else {
Update(1,x+1,y);
}
}
}
return 0;
}