题意:
给你
n
n
n个数
m
i
m_i
mi,要求找一个序列
a
i
a_i
ai满足
a
i
<
=
m
i
a_i<=m_i
ai<=mi并且
a
i
a_i
ai左右不能同时有
a
j
>
a
i
(
j
!
=
i
)
a_j>a_i(j!=i)
aj>ai(j!=i)
求这个序列和最大的情况。
思路:
首先
a
i
a_i
ai左右不能同时有
a
j
>
a
i
(
j
!
=
i
)
a_j>a_i(j!=i)
aj>ai(j!=i),这个形状就是开口向上的二次函数。
那么与他相反的必然就是开口向下的二次函数或者(其左(右)的一部分),因为左右不能同时大于
a
i
a_i
ai
那么就有3种可能:
①左右同时小于等于它
②左大右小
③左小右大
这个就是开口向下的二次函数或者(其左(右)的一部分)这种。
那么暴力做法就是枚举顶点,让其左右2边的都满足下降,同时维护一个最小值,
取每个顶点的最大值即可。
那么优化的话,我们每次枚举顶点,看能不能利用前面的已经求出来的东西,要让其下降,我们找到左边(右)第一个比它小的位置id,然后这个顶点i的答案就是ans[id] + (i-id)*a[i],而得到左边第一个比它小的,可以用单调栈维护,维护一个单调递减栈,因为左(右)边大于当前a[i]的值肯定用不上了,因为如果后面一个数比a[i]大,那么a[i]就是后面一个数的第一个,如果比a[i]小,那么大于它的肯定没用了,维护一个单调递减的栈就好了,同时从后面扫一遍,然后答案就是 m a x ( p r e [ i ] + h e d [ i ] − a [ i ] ) max(pre[i] + hed[i] - a[i]) max(pre[i]+hed[i]−a[i])因为a[i]多算了一次。
code(easy)
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define IOS ios::sync_with_stdio(0)
template <typename T>
inline T read(){T sum=0,fl=1;int ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')fl=-1;
for(;isdigit(ch);ch=getchar())sum=sum*10+ch-'0';
return sum*fl;}
template <typename T>
inline void write(T x) {static int sta[35];int top=0;
do{sta[top++]= x % 10, x /= 10;}while(x);
while (top) putchar(sta[--top] + 48);}
template<typename T>T gcd(T a, T b) {return b==0?a:gcd(b, a%b);}
template<typename T>T exgcd(T a,T b,T &g,T &x,T &y){if(!b){g = a,x = 1,y = 0;}
else {exgcd(b,a%b,g,y,x);y -= x*(a/b);}}
#ifndef ONLINE_JUDGE
#define debug(fmt, ...) {printf("debug ");printf(fmt,##__VA_ARGS__);puts("");}
#else
#define debug(fmt, ...)
#endif
typedef long long ll;
const ll mod = 1e9+7;
int a[man];
int res[man],tp[man];
int main() {
#ifndef ONLINE_JUDGE
//freopen("in.txt", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
int n;
scanf("%d",&n);
for(int i = 1;i <= n;i++){
scanf("%d",&a[i]);
}
ll ans = 0;
for(int i = 1;i <= n;i++){
ll sum = a[i];
int minn = a[i];
tp[i] = a[i];
for(int j = i-1;j >= 1;j--){
minn = min(minn,a[j]);
tp[j] = minn;
sum += minn;
}
minn = a[i];
for(int j = i+1;j <= n;j++){
minn = min(minn,a[j]);
tp[j] = minn;
sum += minn;
}
if(sum>ans){
ans = sum;
for(int j = 1;j <= n;j++){
res[j] = tp[j];
}
}
}
for(int i = 1;i <= n;i++){
printf(i==n?"%d\n":"%d ",res[i]);
}
return 0;
}
code(hard)
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 5e5+10;
#define IOS ios::sync_with_stdio(0)
template <typename T>
inline T read(){T sum=0,fl=1;int ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')fl=-1;
for(;isdigit(ch);ch=getchar())sum=sum*10+ch-'0';
return sum*fl;}
template <typename T>
inline void write(T x) {static int sta[35];int top=0;
do{sta[top++]= x % 10, x /= 10;}while(x);
while (top) putchar(sta[--top] + 48);}
template<typename T>T gcd(T a, T b) {return b==0?a:gcd(b, a%b);}
template<typename T>T exgcd(T a,T b,T &g,T &x,T &y){if(!b){g = a,x = 1,y = 0;}
else {exgcd(b,a%b,g,y,x);y -= x*(a/b);}}
#ifndef ONLINE_JUDGE
#define debug(fmt, ...) {printf("debug ");printf(fmt,##__VA_ARGS__);puts("");}
#else
#define debug(fmt, ...)
#endif
typedef long long ll;
const ll mod = 1e9+7;
int a[man];
int res[man],sta[man];
ll pre[man],hed[man];
int main() {
#ifndef ONLINE_JUDGE
//freopen("in.txt", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
int n;
scanf("%d",&n);
for(int i = 1;i <= n;i++)scanf("%d",&a[i]);
int top = 0;
pre[0] = 0;
for(int i = 1;i <= n;i++){
while(top&&a[sta[top]]>=a[i])top--;
if(!top)pre[i] = 1ll*i*a[i];
else pre[i] = 1ll*(i-sta[top])*a[i] + pre[sta[top]];
sta[++top] = i;
}
top = 0;
hed[n+1] = 0;
for(int i = n;i >= 1;i--){
while(top&&a[sta[top]]>=a[i])top--;
if(!top)hed[i] = 1ll*(n-i+1)*a[i];
else hed[i] = 1ll*(sta[top]-i)*a[i] + hed[sta[top]];
//cout << i << " " << hed[i] << endl;
sta[++top] = i;
}
ll ans = 0,ans_id = 0;
for(int i = 1;i <= n;i++){
ll tp = pre[i]+hed[i]-a[i];
if(tp>ans){
ans = tp;
ans_id = i;
}
}
int minn = a[ans_id];
res[ans_id] = minn;
for(int i = ans_id-1;i >= 1;i--){
minn = min(minn,a[i]);
res[i] = minn;
}
minn = a[ans_id];
for(int i = ans_id+1;i <= n;i++){
minn = min(minn,a[i]);
res[i] = minn;
}
for(int i = 1;i <= n;i++){
printf(i==n?"%d\n":"%d ",res[i]);
}
return 0;
}