zoukankan      html  css  js  c++  java
  • 区间的价值(线段树)百度之星

    区间的价值

    Accepts: 0
    Submissions: 0
    Time Limit: 10000/5000 MS (Java/Others)
    Memory Limit: 65536/65536 K (Java/Others)
    Problem Description

    我们定义“区间的价值”为一段区间的最大值*最小值。

    一个区间左端点在L,右端点在R,那么该区间的长度为(R−L+1)

    现在聪明的杰西想要知道,对于长度为k的区间,最大价值的区间价值是多少。

    当然,由于这个问题过于简单。

    我们肯定得加强一下。

    我们想要知道的是,对于长度为1∼n的区间,最大价值的区间价值分别是多少。

    样例解释:

    长度为1的最优区间为22 答案为66

    长度为2的最优区间为45 答案为44

    长度为3的最优区间为24 答案为26

    长度为4的最优区间为25 答案为26

    长度为5的最优区间为15 答案为16

    Input
    多组测试数据
    第一行一个数n(1<=n<=100000)。
    第二行n个正整数(1<=ai<=10^9),下标从1开始。
    由于某种不可抗力,ai的值将会是1~10^9内随机的一个数。(除了样例)
    Output
    输出共n行,第i行表示区间长度为i的区间中最大的区间价值。
    Sample Input
    5
    1 6 2 4 4
    
    Sample Output
    36
    16
    12
    12
    6

    题解,构造两个线段树,分别求出最大与最小的坐标。然后利用用一个类似快排的方法,每次找到最大最小后,更新所有包含该区间的区间的值,然后选择最小的下标作为分割点,继续递归划分。为什么选最小坐标呢?
    我们假设当前区间为[l,r],该区间的最小值和最大值下标分别为min_p和max_p,那么[l,r]的答案由:
    1、左右端点都在[l,min_p)
    2、左右端点都在(min_p,r]
    3、左端点在[l,min_p)右端点在(min_p,r]
    4、N[min_p]*N[max_p](当前最小值和最大值的乘积)

    上诉四种情况中取最优
    我们发现3不可能比4更优,因为3的最小值一定会是N[min_p],最大值一定小于N[max_p],所以情况3可以剪去。所以直接递归处理1和2就可以。(可以想想为什么不能取max_p作为分割点)

    因为数据是随机的,所以这样递归处理的复杂度和快排类似,总的复杂度是nlognlogn//这里复杂度有点玄学,跑起来飞快。如有错误请指出



    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    #define lson l , m , rt << 1
    #define rson m + 1 , r , rt << 1 | 1
    const int maxn = 100010;
    int MAX[maxn<<2];
    int MIN[maxn<<2];
    long long ans[maxn];
    long long N[maxn];
    int Pos=0,n;
    long long read()
    {
        long long ans=0;
        char last=' ',ch=getchar();
        while(ch<'0' || ch>'9')last=ch,ch=getchar();
        while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
        if(last=='-')ans=-ans;
        return ans;
    }
    void PushUP_max(int rt)
    {
        if (N[MAX[rt<<1]] > N[MAX[rt<<1|1]])
            MAX[rt] = MAX[rt<<1] ;
        else
            MAX[rt] =MAX[rt<<1|1];
    }
    void PushUP_min(int rt)
    {
        if (N[MIN[rt<<1]] < N[MIN[rt<<1|1]])
            MIN[rt] = MIN[rt<<1] ;
        else
            MIN[rt] =MIN[rt<<1|1];
    }
    void build_max(int l,int r,int rt)
    {
        if (l == r)
        {
            MAX[rt]=++Pos;
            return ;
        }
        int m = (l + r) >> 1;
        build_max(lson);
        build_max(rson);
        PushUP_max(rt);
    }
    void build_min(int l,int r,int rt)
    {
        if (l == r)
        {
            MIN[rt]=MAX[rt];
            return ;
        }
        int m = (l + r) >> 1;
        build_min(lson);
        build_min(rson);
        PushUP_min(rt);
    }
    int query_max(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=0;
        N[0]=0;
        if (L <= m)
        {
            int tl=query_max(L , R , lson);
            if (N[tl]>N[ret])
                ret = tl;
        }
        if (R > m)
        {
            int tr=query_max(L , R , rson);
            if (N[tr]>N[ret])ret = tr;
        }
        return ret;
    }
    int query_min(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 =0;
        N[0]=999999999;
        if (L <= m)
        {
            int tl=query_min(L , R , lson);
            if (N[tl]<N[ret])
                ret = tl;
        }
        if (R > m)
        {
            int tr=query_min(L , R , rson);
            if (N[tr]<N[ret])ret = tr;
        }
        return ret;
    }
    void sovle(int l,int r)
    {
        if (l>r) return ;
        int max_p=query_max(l , r , 1 , n , 1);
        int min_p=query_min(l , r , 1 , n , 1);
        long long num=N[max_p]*N[min_p];
        int nl,nr;
        if(max_p>min_p)
        {
            nl=min_p;
            nr=max_p;
        }
        else
        {
            nr=min_p;
            nl=max_p;
        }
        for (int i=nr-nl+1; i<=r-l+1; i++) ans[i]=max(ans[i],num);
        sovle(l,min_p-1);
        sovle(min_p+1,r);
    }
    int main()
    {
        while(~scanf("%d",&n))
        {
            getchar();
            memset(ans,0,sizeof(ans));
            for (int i=1; i<=n; i++)
                N[i]=read();
            Pos=0;
            build_max(1 , n , 1);
            build_min(1 , n , 1);
            sovle(1,n);
            for (int i=1; i<=n; i++)
                printf("%I64d
    ",ans[i]);
        }
        return 0;
    }
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  • 相关阅读:
    geoserver发布地图服务WMTS
    geoserver发布地图服务WMS
    geoserver安装部署步骤
    arcgis api 3.x for js 入门开发系列十四最近设施点路径分析(附源码下载)
    arcgis api 3.x for js 入门开发系列十三地图最短路径分析(附源码下载)
    cesium 之自定义气泡窗口 infoWindow 后续优化篇(附源码下载)
    arcgis api 3.x for js 入门开发系列十二地图打印GP服务(附源码下载)
    arcgis api 3.x for js 入门开发系列十一地图统计图(附源码下载)
    arcgis api 3.x for js 入门开发系列十叠加 SHP 图层(附源码下载)
    arcgis api 3.x for js入门开发系列九热力图效果(附源码下载)
  • 原文地址:https://www.cnblogs.com/scaugsh/p/5536681.html
Copyright © 2011-2022 走看看