https://vjudge.net/problem/CodeForces-1313C2
思路:不難想到枚舉一個最高點,然後非降,非升即可滿足題意。實際上這也是簡單版的做法。我們搞兩個數組,表示當非降時所能得到的最高分,表示當非升時所能得到的最高分,那麼只需掃一遍數組取即可。現在考慮怎麼計算這兩個數組,以爲例,假設已知,如果,顯然有,否則我們找到的最大的,顯然有。通過單調棧就可以求得數組,數組同理。
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define pr pair<double,int>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn=5e5+5;
int n;
ll a[maxn],l[maxn],r[maxn];
stack<int> s;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%I64d",&a[i]);
for(int i=1;i<=n;i++)
{
while(!s.empty()&&a[s.top()]>=a[i])
s.pop();
if(s.empty())
l[i]=i*a[i];
else
l[i]=l[s.top()]+(i-s.top())*a[i];
s.push(i);
}
while(!s.empty())
s.pop();
for(int i=n;i>=1;i--)
{
while(!s.empty()&&a[s.top()]>=a[i])
s.pop();
if(s.empty())
r[i]=(n-i+1)*a[i];
else
r[i]=r[s.top()]+(s.top()-i)*a[i];
s.push(i);
}
ll ans=0,idx=0;
for(int i=1;i<=n;i++)
if(l[i]+r[i]-a[i]>ans)
ans=l[i]+r[i]-a[i],idx=i;
for(int i=idx-1;i>=1;i--)
a[i]=min(a[i],a[i+1]);
for(int i=idx+1;i<=n;i++)
a[i]=min(a[i-1],a[i]);
for(int i=1;i<=n;i++)
printf("%I64d ",a[i]);
return 0;
}