您的位置:首页 > 理论基础 > 计算机网络

ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛 题目9 : Minimum(线段树)

2017-09-23 16:56 441 查看
时间限制: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


恰巧学到线段树,于是就用上了。我没看这个题目,队友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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐