洛谷 P2659 美丽的序列

来源:互联网 发布:文件管理系统源码 编辑:程序博客网 时间:2024/05/21 17:01

题目来源:https://www.luogu.org/problem/show?pid=2659#sub


到数据范围非常大,然而竟可以水过。


fl[i]表示从i为最小值的区间的右端点,fr[i]表示以i为最小值的左端点。


核心代码,求fl[i]:


if(a[i-1]>a[i])fl[i]=i;else{     int n=i;     while(a[n-1]>a[i])n=fl[n-1];     fl[i]=n;}

求fr[i]类似。


注意,为保证端点均能被取得,需令a[0]=a[n+1]=-1。


代码:


#include <algorithm>#include <iostream>#include <cstring>#include <cstdlib>#include <sstream>#include <cstdio> #include <string>#include <vector>#include <cmath>#include <ctime>#include <stack>#include <queue>#include <set>#include <map>using namespace std;const int maxn=2e6+10;int a[maxn]={0};int n;int fl[maxn]={0},fr[maxn]={0};int main(){    scanf("%d",&n);    for(int i=1;i<=n;i++)scanf("%d",&a[i]);    long long tot=0;    a[n+1]=a[0]=-1;    for(int i=1;i<=n;i++)    {        if(a[i]>=a[i-1])fl[i]=i;        else        {            int n=i;            while(a[n-1]>=a[i])n=fl[n-1];            fl[i]=n;        }    }    for(int i=n;i>=1;i--)    {        if(a[i]>a[i+1])fr[i]=i;        else        {            int n=i;            while(a[n+1]>a[i])n=fr[n+1];            fr[i]=n;        }    }    for(int i=1;i<=n;i++)tot=max((long long)(fr[i]-fl[i]+1)*a[i],tot);    printf("%lld",tot);    return 0;}


0 0
原创粉丝点击