3780. 构造数组 (单调栈)
Posted CCSU_Cola
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3780. 构造数组 (单调栈)相关的知识,希望对你有一定的参考价值。
题意:
给定一个长度为 n 的整数数组 m1,m2,…,mn。
现在,请你构造一个数组 a1,a2,…,an。
对于构造的数组,有以下三点要求:
- ∀i∈[1,n],1≤ai≤mi 成立。
- ∀i∈[1,n], 不存在数对 j,k,i 同时满足 j<i<k 且 aj>ai<ak。
- 数组中所有元素之和尽可能大。
请输出任意合理方案。
思路:
由题知道,形成的数组一定是只有一个峰的,也就是说只需要选定其中一个点为最大值,两边非递增就可以了,于是可以先用单调栈分别维护某个值为峰时的前缀和与后缀和,找到以最大值时的峰在哪,就可以按照非递增的思路得到数组了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll a[500010];
ll L[500010],R[500010];
int st[510000];
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
int top=0;
for(int i=1;i<=n;i++){
while(top&&a[st[top]]>=a[i]){
top--;
}
L[i]=L[st[top]]+(ll)(i-st[top])*a[i];
st[++top]=i;
}
top=0;
st[0]=n+1;
for(int i=n;i>=1;i--){
while(top&&a[st[top]]>=a[i]){
top--;
}
R[i]=R[st[top]]+(ll)(st[top]-i)*a[i];
st[++top]=i;
}
ll res=0;
int k;
for(int i=1;i<=n;i++){
if(res<L[i]+R[i+1])res=L[i]+R[i+1],k=i;
}
for(int i=k-1;i>=1;i--){
a[i]=min(a[i],a[i+1]);
}
for(int i=k+2;i<=n;i++){
a[i]=min(a[i],a[i-1]);
}
for(int i=1;i<=n;i++){
printf("%d ",a[i]);
}
}
以上是关于3780. 构造数组 (单调栈)的主要内容,如果未能解决你的问题,请参考以下文章