【hiho1586】Minimum(線段樹)
#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
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);
}
}
}