#1586 : 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
【题意】
给定一个序列,当执行操作1时,输出在[l,r]这个区间内,乘积最小的数,当执行操作2时,更改x位置的元素为y。
【解题思路】
其实这道题只要用线段树维护最大值和最小值就可以啦。
因为当最小值为负数时,如果最大值为正数,那么最大值*最小值即为最小的数。若最大值为负数,那么最大值*最大值即为最小的数。
当最小值为正数时,如果最大值为正数,那么最小值*最小值即为最小的数。
嗯只是线段树的基本操作而已...布吉岛我在怕啥。
【代码】
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=8e5;
const int INF=0x3f3f3f3f;
LL pmax,pmin;
struct Node
{
int l,r;
LL Min,Max;
}tree[maxn];
void build(int k,int ll,int rr)
{
tree[k].l=ll,tree[k].r=rr;
if(tree[k].l==tree[k].r)
{
scanf("%lld",&tree[k].Min);
tree[k].Max=tree[k].Min;
return;
}
int m=(ll+rr)/2;
build(k*2,ll,m);
build(k*2+1,m+1,rr);
tree[k].Max=max(tree[k*2].Max,tree[2*k+1].Max);
tree[k].Min=min(tree[k*2].Min,tree[2*k+1].Min);
}
void change_point(int k,int v,int pos)
{
if(tree[k].l==tree[k].r)
{
tree[k].Max=v;
tree[k].Min=v;
return ;
}
int m=(tree[k].l+tree[k].r)/2;
if(pos<=m)change_point(k*2,v,pos);
else change_point(k*2+1,v,pos);
tree[k].Max=max(tree[k*2].Max,tree[k*2+1].Max);
tree[k].Min=min(tree[k*2].Min,tree[k*2+1].Min);
}
void ask_interval(int a,int b,int k)
{
if(tree[k].l>=a && tree[k].r<=b)
{
pmax=max(pmax,tree[k].Max);
pmin=min(pmin,tree[k].Min);
return;
}
int m=(tree[k].l+tree[k].r)/2;
if(a<=m)ask_interval(a,b,k*2);
if(b>m)ask_interval(a,b,k*2+1);
tree[k].Max=max(tree[k*2].Max,tree[k*2+1].Max);
tree[k].Min=min(tree[k*2].Min,tree[k*2+1].Min);
}
int main()
{
int T,q,k;
scanf("%d",&T);
while(T--)
{
int n=1;
scanf("%d",&k);
for(int i=1;i<=k;i++)
n*=2;
build(1,1,n);
scanf("%d",&q);
while(q--)
{
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(op==1)
{
pmin=INF;
pmax=-INF;
ask_interval(x+1,y+1,1);
if(pmin>=0)printf("%lld\n",pmin*pmin);
else
{
if(pmax>=0)printf("%lld\n",pmin*pmax);
else printf("%lld\n",pmax*pmax);
}
}
else change_point(1,y,x+1);
}
}
}