• P2659 美丽的序列


    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。 提示 你可能需要一个读入优化。

    做法1

    分析

    我的天啊,第二个测试点964ms卡过。。。(再交一次就不一定过了。。。90)

    然后写一下思路吧:

    用线段树logn找出最小值,以及最小值的位置,

    包含最小值的所有区间的最大值,应该是区间长度最长的。

    当前区间[l,r],最小值mn,它的位置pos,

    包含最小值:[l,r]的答案就是mn*(r-l+1)

    不包含最小值:将[l,r]分成两段,[l,pos-1],[pos+1,r]在这两个区间递归,像上面这样做。详见代码

    (笛卡尔树)

    code

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 #define lson l,m,rt<<1
     5 #define rson m+1,r,rt<<1|1
     6 #define INF 0x7fffffff
     7 #define MAXN 2000100
     8 #define LL long long
     9 struct MN {
    10     int mn,pos;
    11 }t[MAXN<<2];
    12 LL ans = 0;
    13 int n;
    14 inline int read() {
    15     int x = 0,f = 1;char ch = getchar();
    16     for (; ch<'0'||ch>'9'; ch = getchar())
    17         if (ch=='-') f = -1;
    18     for (; ch>='0'&&ch<='9'; ch = getchar())
    19         x = x*10+ch-'0';
    20     return x*f;
    21 }
    22 inline void pushup(int rt) {
    23     if (t[rt<<1].mn < t[rt<<1|1].mn) t[rt].mn = t[rt<<1].mn, t[rt].pos = t[rt<<1].pos;
    24     else t[rt].mn = t[rt<<1|1].mn, t[rt].pos = t[rt<<1|1].pos;
    25 }
    26 void build(int l,int r,int rt) {
    27     if (l==r) {
    28         t[rt].mn = read();
    29         t[rt].pos = l;
    30         return;
    31     }
    32     int m = (l+r)>>1;
    33     build(lson);
    34     build(rson);
    35     pushup(rt);
    36 }
    37 MN query(int l,int r,int rt,int L,int R) {
    38     if (L<=l && r<=R) {
    39         return t[rt];
    40     }
    41     int m = (l+r)>>1;
    42     MN t,ret;
    43     ret.mn = INF;
    44     if (L<=m) ret = query(lson,L,R);
    45     if (R>m)  {
    46         t = query(rson,L,R);
    47         if (t.mn < ret.mn) ret = t;
    48     } 
    49     return ret;
    50 }
    51 void solve(int l,int r) {
    52     MN m = query(1,n,1,l,r);
    53     ans = max(ans,1ll*(r-l+1)*m.mn);
    54     if (l<m.pos) solve(l,m.pos-1);
    55     if (m.pos<r) solve(m.pos+1,r);
    56 }
    57 int main() {
    58     n = read();
    59     build(1,n,1);
    60     solve(1,n);
    61     printf("%lld",ans);    
    62     return 0;
    63 }

     

    做法2

    分析

    分别求出每个元素向左和向右扩展的最大长度

    最后每个元素获得的最大值等于(向左延伸的长度 + 向右延伸的长度 + 1)* 元素的值

    使用单调栈可以O(n)算出。

    code

     1 #include<cstdio>
     2 #include<algorithm>
     3 
     4 using namespace std;
     5 
     6 #define INF 0x7fffffff
     7 #define MAXN 2000100
     8 #define LL long long
     9 
    10 int st[MAXN],pos[MAXN],a[MAXN],top,R[MAXN];
    11 
    12 inline int read() {
    13     int x = 0,f = 1;char ch = getchar();
    14     for (; ch<'0'||ch>'9'; ch = getchar())
    15         if (ch=='-') f = -1;
    16     for (; ch>='0'&&ch<='9'; ch = getchar())
    17         x = x*10+ch-'0';
    18     return x*f;
    19 }
    20 
    21 int main() {
    22     
    23     int n = read();
    24     LL ans = 0,sum;
    25     for (int i=1; i<=n; ++i) a[i] = read();
    26     
    27     a[0] = a[n+1] = -1;
    28     st[(top=0)] = 0;
    29     for (int i=1; i<=n+1; ++i) {
    30         while (a[st[top]] > a[i]) {
    31             R[st[top]] = i-1;
    32             top--;
    33         }
    34         st[++top] = i;
    35     }
    36     
    37     st[(top=0)] = 0;
    38     for (int i=n; i>=0; --i) {
    39         while (a[st[top]] > a[i]) {
    40             sum = 1ll*(R[st[top]]-i)*a[st[top]];//right R[],left i+1 R-(i+1)+1->R-i
    41             ans = max(ans,1ll*(R[st[top]]-i)*a[st[top]]); 
    42             top--;
    43         }
    44         st[++top] = i;
    45     }
    46     
    47     printf("%lld",ans);
    48     
    49     return 0;
    50 } 
  • 相关阅读:
    mongodb性能测试:long时间戳与string格式时间
    .netcore mongodb 分页+模糊查询+多条件查询
    .netcore 图片处理
    ELEMENT-UI 封装el-table 局部刷新row
    vue-upload 封装组件-上传组件
    vue实现v-model父子组件间的双向通信
    cc.AudioSource
    Chrome插件:本地程序实现验证码破解(浏览器与本地进程通信)
    Chrome插件:微信公众号自动登录(chrome.extension)
    Chrome插件:浏览器后台与页面间通信
  • 原文地址:https://www.cnblogs.com/mjtcn/p/7673754.html
Copyright © 2020-2023  润新知