【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: 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);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_39826163/article/details/83829529