ACM-ICPC北京赛区(2017)网络赛_Minimum

时间:2023-03-09 05:10:41
ACM-ICPC北京赛区(2017)网络赛_Minimum

题目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
4 典型的线段树单点更新与区间最大(小)值,没什么奥妙,但是自己还是打挫了,连WA带T13发,233,最终在一位小姐姐的指导小改掉一些细节错误成功A一发 附上AC代码:
 #include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<cstring> using namespace std; const int MAXNODE = (<<)+;
const int MAX = 2e7+;//2*10^6+10
const int INF = 0x7fffffff; struct NODE{
int maxvalue, minvalue;
int left, right;
}node[MAXNODE]; int father[MAX]; void BuildTree(int i, int left, int right)
{
node[i].minvalue = INF;
node[i].maxvalue = -INF;
node[i].left = left;
node[i].right = right;
if(right == left)
{
father[left] = i;
return;
}
BuildTree(i<<, left, (int)(floor(left+right)/2.0));
BuildTree((i<<)+, (int)(floor(left+right)/2.0)+, right);
} //自底向上更新
void UpdateTree(int ri)
{
if(ri <= )
return;
int fi = ri/;
int a = node[fi<<].maxvalue;
int b = node[(fi<<)+].maxvalue;
node[fi].maxvalue = max(a, b);
a = node[fi<<].minvalue;
b = node[(fi<<)+].minvalue;
node[fi].minvalue = min(a, b);
UpdateTree(ri/);
} int Max, Min; //自顶向上查询
void Query_max(int i, int l, int r)
{
if(node[i].left == l && node[i].right == r)
{
Max = max(Max, node[i].maxvalue);
return;
} i <<= ;
if(l <= node[i].right)
{
if(r <= node[i].right)
{
Query_max(i, l, r);
}
else
{
Query_max(i, l, node[i].right);
}
}
i++;
if(r >= node[i].left)
{
if(l >= node[i].left)
{
Query_max(i, l, r);
}
else
{
Query_max(i, node[i].left, r);
}
}
} void Query_min(int i, int l, int r)
{
if(node[i].left == l && node[i].right == r)
{
Min = min(Min, node[i].minvalue);
return;
} i <<= ;
if(l <= node[i].right)
{
if(r <= node[i].right)
{
Query_min(i, l, r);
}
else
{
Query_min(i, l, node[i].right);
}
}
i++;
if(r >= node[i].left)
{
if(l >= node[i].left)
{
Query_min(i, l, r);
}
else
{
Query_min(i, node[i].left, r);
}
}
} int main()
{
int k, t, n, g, a, b, c;
long long ans;
ios::sync_with_stdio(false);
cin>>t;
//cout<<INF<<-INF<<endl;
while(t--)
{
cin>>k;
BuildTree(, , <<k);
for(int i = ; i <= <<k; i++)
{
cin>>g;
node[father[i]].maxvalue = node[father[i]].minvalue = g;
UpdateTree(father[i]);
}
cin>>n;
for(int i = ; i <= n; i++)
{
Max = -INF;
Min = INF;
cin>>a>>b>>c;
if(a == )
{
Query_max(, b+, c+);
Query_min(, b+, c+);
//cout<<Max<<" "<<Min<<endl;
if(Max <= )
{
ans = (long long)Max*Max;
cout<<ans<<endl;
}
else if(Min >= )
{
ans = (long long)Min*Min;
cout<<ans<<endl;
}
else
{
ans = (long long)Min*Max;
cout<<ans<<endl;
}
}
else if(a == )
{
node[father[b+]].maxvalue = node[father[b+]].minvalue = c;
UpdateTree(father[b+]);
}
}
}
return ;
}