某看起来会做的数据结构题

P2659 美丽的序列

题目背景

GD是一个热衷于寻求美好事物的人,一天他拿到了一个美丽的序列。

题目描述

为了研究这个序列的美丽程度,GD定义了一个序列的“美丽度”和“美丽系数”:对于这个序列的任意一个区间[l,r],这个区间的“美丽度”就是这个区间的长度与这个区间的最小值的乘积,而整个序列的“美丽系数”就是它的所有区间的“美丽度”的最大值。现在GD想要你帮忙计算这个序列的“美丽系数”。

输入输出格式

输入格式:
第一行一个整数n,代表序列中的元素个数。 第二行n个整数a1、a2„an,描述这个序列。

输出格式:
一行一个整数,代表这个序列的“美丽系数”。

输入输出样例

输入样例#1: 复制
3
1 2 3
输出样例#1: 复制
4
说明

样例解释 选取区间[2,3],可以获得最大“美丽系数”为2*2=4。 数据范围 对于20%的数据,n<=2000; 对于60%的数据,n<=200000; 对于100%的数据,1<=n<=2000000,0<=ai<=2000000。 提示 你可能需要一个读入优化。

这个题目很熟悉
以前接触过
首先这是一个分治算法
找出整段序列的最小值
然后递归最小值两侧求解

这个做法可以用线段树等结构维护
然后还有一个比较简单的单调栈做法

#include<iostream>
#include<cstdio>
#define N 20000005
using namespace std;

int anss;

struct node{
    int l,r,s,pos;
};

struct segment{
    int n;
    node t[N];
    void PushUp(int ret){
        if(t[t[ret<<1].pos].s>t[t[ret<<1|1].pos].s)
            t[ret].pos=t[t[ret<<1].pos].s;
        else t[ret].pos=t[t[ret<<1|1].pos].s;
    }
    inline void Build(int l,int r,int ret){
        t[ret].l=l;t[ret].r=r;
        if(l==r){
            t[ret].pos=ret;
            anss=max(anss,t[ret].s);
            scanf("%d",&t[ret].s);
            return;
        }
        int mid=(l+r)>>1;
        Build(l,mid,ret<<1);
        Build(mid+1,r,ret<<1|1);
        PushUp(ret);
    }
    int Gmin(int a,int b){
        return t[a].s>t[a].s?a:b;
    }
    inline int query(int ret,int L,int R){
        int l=t[ret].l,r=t[ret].r;
        if(l>=L&&r<=R)
            return t[ret].pos;
        int mid=(l+r)>>1;
        int ans=0x7fffffff;
        if(R>mid)ans=Gmin(ans,query(ret<<1|1,L,R));
        if(L<=mid)ans=Gmin(ans,query(ret<<1,L,R));
        return ans;
    }
}Now;

int ans(int l,int r){
    if(l==r)return 0;
    int pos=Now.query(1,l,r);
    int minl=Now.t[pos].l;
    int ansl=0;
    ansl=max((r-l+1)*Now.t[pos].s,max(ans(l,minl-1),ans(minl+1,r)));
    return ansl;
}
int main(){
    int n,m;
    cin>>n>>m;
    Now.Build(1,n,1);
    printf("%d",ans(1,n));
    return 0;
}

posted @ 2017-11-21 20:55  Grary  阅读(133)  评论(0编辑  收藏  举报
博客园 首页 私信博主 编辑 关注 管理 新世界