• HDU 5696 区间的价值


    区间的价值

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 1341    Accepted Submission(s): 600

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

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

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

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

    我们肯定得加强一下。

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

    样例解释:

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

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

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

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

    长度为5的最优区间为15 答案为16
     
    Input
    多组测试数据

    第一行一个数n(1n100000)

    第二行n个正整数(1ai109),下标从1开始。

    由于某种不可抗力,ai的值将会是1109内<b style="color:red;">随机产生</b>的一个数。(除了样例)
     
    Output
    输出共n行,第i行表示区间长度为i的区间中最大的区间价值。
     
    Sample Input
    5 1 6 2 4 4
     
    Sample Output
    36 16 12 12 6
     
    Source
     
    Recommend
    wange2014   |   We have carefully selected several similar problems for you:  6216 6215 6214 6213 6212
    思路:
    首先回顾一下快排的思想:快排每次划分,都是从随机找一个值作为阀值(简单起见,通常找第一个),然后从需要划分的区间的最右端找比阀值小的值,用这个值去填最左端那个位置,从最左端找比阀值大的值,用这个值填最右端那个位置,交替去找,知道low和high相等,然后将阀值放到该位置,这次划分结束,阀值左边的值都比阀值右边的值要小。递归排序阀值左边的区间和右边的区间,最终保证有序。
    用一颗线段树维护某一段区间中的最小最大值的编号。
    这个题目要求的是区间长度为i的区间中最小值和最大值的乘积的最大值。我们拿到一段区间l, r,假设这段区间中的最小值的位置为idmin,最大值的位置为idmax,这段区间中的所有区间长度大于等于abs(idmin-idmax)+1的区间都可以被a[idmin]*a[idmax]更新到,由于我们要的是最大值,所以我们以最小值为分隔,递归求解左部分和右部分,都不能包含分隔。
     错因:
    long long tmp=1ll*num[minn]*num[maxn];没有强制转化为long long
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 100001
    using namespace std; 
    int n,num[MAXN];
    struct nond{
        int minn,maxn,l,r;
    }tree[MAXN*4];
    long long ans[MAXN];
    void up(int now){
        if(num[tree[now*2].maxn]>num[tree[now*2+1].maxn])
            tree[now].maxn=tree[now*2].maxn;
        else tree[now].maxn=tree[now*2+1].maxn;
        if(num[tree[now*2].minn]<num[tree[now*2+1].minn])
            tree[now].minn=tree[now*2].minn;
        else tree[now].minn=tree[now*2+1].minn;
    }
    void build(int now,int l,int r){
        tree[now].l=l;tree[now].r=r;
        if(l==r){
            tree[now].minn=l;
            tree[now].maxn=l;
            return ;
        }
        int mid=(tree[now].l+tree[now].r)/2;
        build(now*2,l,mid);
        build(now*2+1,mid+1,r);
        up(now);
    }
    int query(int now,int l,int r,int opt){
        if(tree[now].l==l&&tree[now].r==r){
            if(opt==0)    return tree[now].maxn;
            else if(opt==1)    return tree[now].minn;
        }
        int mid=(tree[now].l+tree[now].r)/2;
        if(r<=mid)    return query(now*2,l,r,opt);
        else if(l>mid)    return query(now*2+1,l,r,opt);
        else{
            if(opt==0){
                if(num[query(now*2,l,mid,opt)]>num[query(now*2+1,mid+1,r,opt)])
                    return query(now*2,l,mid,opt);
                else return query(now*2+1,mid+1,r,opt);
            }    
            else{
                if(num[query(now*2,l,mid,opt)]<num[query(now*2+1,mid+1,r,opt)])
                    return query(now*2,l,mid,opt);
                else return query(now*2+1,mid+1,r,opt);
            }
        }
    }
    void dfs(int l,int r,int now){
        if(r<l)    return ;
        int maxn=query(1,l,r,0);
        int minn=query(1,l,r,1);
        if(maxn>minn)    swap(minn,maxn);
        long long tmp=1ll*num[minn]*num[maxn];
        for(int i=minn-maxn+1;i<=r-l+1;i++)
            ans[i]=max(ans[i],tmp);
        if(num[minn]>num[maxn]){
            dfs(l,maxn-1,now);
            dfs(maxn+1,r,now);
        }
        else{
            dfs(l,minn-1,now);
            dfs(minn+1,r,now);
        }
    }
    int main(){
        while(scanf("%d",&n)!=EOF){
            memset(tree,0,sizeof(tree));
            memset(ans,0,sizeof(ans));
            for(int i=1;i<=n;i++)
                scanf("%d",&num[i]);
            build(1,1,n);
            dfs(1,n,n);
            for(int i=1;i<=n;i++)
                cout<<ans[i]<<endl;
        }    
        return 0;
    }
    细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
  • 相关阅读:
    Vue ref
    Vue 全局注册
    【华为云技术分享】用Flask开发Web版日历应用
    【华为云技术分享】鲲鹏展翅 力算未来 | openEuler操作系统源代码正式开放
    【华为云技术分享】17张图带你解析红黑树的原理!保证你能看懂!
    【华为云技术分享】自动搭建openEuler虚拟机QEMU运行环境
    【华为云技术分享】【玩转Atlas200DK系列】应用开发之 交叉编译第三方库并在工程中使用(jsoncpp)
    【华为云技术分享】GitHub联合开发
    【华为云技术分享】【DevCloud•敏捷智库】读懂敏捷需求管理的4个关键词
    【华为云技术分享】iSulad轻量化容器实践解析
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/7589060.html
Copyright © 2020-2023  润新知