题目链接:http://codeforces.com/contest/1313/problem/C2
题意:有n个房子,每个房子可以建的最高层数为a[i],但不可以出现相邻左右两边房子的层数都比中间高的情况,要求总共层数要尽可能的多,输出每个房子应该建几层。
思路:记录左边比自己小的第一个元素,同时可以求出当i为顶端是的前缀和。然后记录右边第一个比自己小的元素,同时可以求出当i为顶端是的后缀和。然后再遍历一篇,看谁为顶端时,总层数最多,最后再依次确定层数即可。
#include<stdio.h> #include<iostream> #include<string.h> #include<math.h> #include<string> #include<algorithm> #include<queue> #include<map> typedef long long ll; using namespace std; priority_queue<pair<ll, ll> >que; ll a[500005],b[500005],c[500005],sum[500005],sum1[500005]; int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); for(int i=1;i<=n;i++) { if(a[i-1]<=a[i]) { b[i]=i-1; sum[i]=sum[i-1]+a[i]; } else { int x=i-1; while(1) { x=b[x]; if(a[x]<=a[i]) { sum[i]=sum[x]+(i-x)*a[i]; b[i]=x; break; } } } } for(int i=n;i>=1;i--) { if(a[i]>=a[i+1]) { c[i]=i+1; sum1[i]=sum1[i+1]+a[i]; } else { int x=i+1; while(1) { x=c[x]; if(a[x]<=a[i]) { sum1[i]=sum1[x]+(x-i)*a[i]; c[i]=x; break; } } } } ll ma=0,p; for(int i=1;i<=n;i++) { if(sum[i]+sum1[i]-a[i]>ma) { ma=sum[i]+sum1[i]-a[i]; p=i; } } ll mi=a[p]; for(int i=p-1;i>=1;i--) { mi=min(mi,a[i]); a[i]=mi; } mi=a[p]; for(int i=p+1;i<=n;i++) { mi=min(mi,a[i]); a[i]=mi; } for(int i=1;i<n;i++) printf("%lld ",a[i]); printf("%lld ",a[n]); }