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

2017ICPC北京赛区网络赛 Minimum(数学+线段树)

2017-09-25 20:35 351 查看

描述

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

分析得出,一区间的乘积最小值,只有三种情况
1.最大值的平方(最大值为负数)
2.最小值的平方(最小值为正数)
3.最大值与最小值的乘积(最大值是正,最小值为负)
得到此结果后,只需改一下线段树的模板,将每段区间的最大最小值保存下来即可。


#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
const long long Max=140000;
int n;
struct node
{
long long b,s;
}Tree[Max<<2];
long long bb,ss;
void build(int k,int l,int r)//建线段树,k表示子节点坐标
{
if(l == r)
{
scanf("%lld",&Tree[k].b);
Tree[k].s=Tree[k].b;
}
else
{
int mid = (l+r)/2;
build(k*2,l,mid);
build(k*2+1,mid+1,r);
Tree[k].b=max(Tree[k*2].b, Tree[k*2+1].b);
Tree[k].s=min(Tree[k*2].s, Tree[k*2+1].s);
}
}
void query(int a,int b,int k,int l,int r)//a,b是当前查询区间,k是当前的根节点,l,r是要求查询区间
{
if(a >= l && b <= r)
{
bb=max(bb,Tree[k].b);
ss=min(ss,Tree[k].s);
//return min(min(Tree[k].b*Tree[k].b,Tree[k].b*Tree[k].s),Tree[k].s*Tree[k].s);
return;
}
else
{
//long long ans = Max*Max;
int mid = (a+b)/2;
if(l <= mid)query(a,mid,k*2,l,r);
if(r > mid) query(mid+1,b,k*2+1,l,r);
return;
//return ans;
}
}
void update(int l,int r,int k,int pos,long long v)//l,r是查询区间,k是当前根节点,pos是查询位置
{
if(l == r)
{
Tree[k].b=v;
Tree[k].s=v;
}
else{
int mid = (l+r)/2;
if(pos <= mid) update(l,mid,k*2,pos,v);
if(pos > mid) update(mid+1,r,k*2+1,pos,v);
Tree[k].b=max(Tree[k*2].b, Tree[k*2+1].b);
Tree[k].s=min(Tree[k*2].s, Tree[k*2+1].s);
}
}

int main()
{
int T,l,r,pos;
long long val;
int k,c,order;
scanf("%d",&T);
for(int t=1;t<=T;t++)
{

scanf("%d",&k);
n=pow(2.0,k);
build(1,1,n);
scanf("%d",&c);
while(c--)
{
scanf("%d",&order);
if(order==1)
{
scanf("%d%d",&l,&r);
bb=-Max;ss=Max;
long long tmpans;
query(1,n,1,l+1,r+1);
tmpans= min(min(bb*bb,bb*ss),ss*ss);
printf("%lld\n",tmpans);
}
else if(order==2)//点更新
{
scanf("%d%lld",&pos,&val);
update(1,n,1,pos+1,val);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐