-
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.
恰巧学到线段树,于是就用上了。我没看这个题目,队友A的。
题目有两种操作:1求区间内最小两个数的乘积,(注意一个点也是乘积),2将x得值换为y
如果区间内有正有负那么最小积就是最小与最大的乘积,如果区间内都正或者都负了,那么结果就是绝对值最小的数的平方,题目维护三个线段树,分别求的是区间最小,最大,和绝对值最小。注意下标从0开始
代码:
#include<iostream>
#include<string>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iomanip>
#include<queue>
#include<cstring>
#include<map>
#include<vector>
using namespace std;
typedef long long ll;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int maxn =131100;
int MAX[maxn<<2],MIN[maxn<<2],MID[maxn<<2];
int go(int a,int b)
{
if(abs(a)<abs(b))
return a;
else return b;
}
void PushUPmax(int rt) {
MAX[rt] = max(MAX[rt<<1] , MAX[rt<<1|1]);
}
void PushUPmin(int rt) {
MIN[rt] = min(MIN[rt<<1] , MIN[rt<<1|1]);
}
void PushUPmid(int rt) {
MID[rt] = go(MID[rt<<1] , MID[rt<<1|1]);
}
void build(int l,int r,int rt) {
if (l == r) {
scanf("%d",&MAX[rt]);
MIN[rt]=MID[rt]=MAX[rt];
return ;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
PushUPmax(rt);
PushUPmin(rt);
PushUPmid(rt);
}
void update(int p,int sc,int l,int r,int rt) {
if (l == r) {
MIN[rt]=MID[rt]=MAX[rt] = sc;
return ;
}
int m = (l + r) >> 1;
if (p <= m) update(p , sc , lson);
else update(p , sc , rson);
PushUPmax(rt);
PushUPmin(rt);
PushUPmid(rt);
}
int querymin(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 , querymin(L , R , lson));
if (R > m) ret = min(ret , querymin(L , R , rson));
return ret;
}
int querymax(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 , querymax(L , R , lson));
if (R > m) ret = max(ret , querymax(L , R , rson));
return ret;
}
int querymid(int L,int R,int l,int r,int rt) {
if (L <= l && r <= R) {
return MID[rt];
}
int m = (l + r) >> 1;
int ret = maxn;
if (L <= m) ret = go(ret , querymid(L , R , lson));
if (R > m) ret = go(ret , querymid(L , R , rson));
return ret;
}
int main() {
int T,n,m;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
n=pow(2,n);
build(1 , n , 1);
scanf("%d",&m);
while (m --)
{
int a , b , c;
scanf("%d%d%d",&c,&a,&b);
a++;
if (c == 1)
{
b++;
ll t1=(ll)querymin(a , b , 1 , n , 1);
ll t2=(ll)querymax(a , b , 1 , n , 1);
ll t3=(ll)querymid(a , b , 1 , n , 1);
ll ans;
//cout<<t1<<" "<<t2<<endl;
if(t1<=0&&t2>=0)
{
ans=t1*t2;
printf("%lld\n",ans);
}
else if(t1>0||t2<0)
{
ans=t3*t3;
printf("%lld\n",ans);
}
}
else update(a , b , 1 , n , 1);
}
}
return 0;
}