Codeforces Round #622 (Div. 2)C(单调栈,DP)

构造出的结果一定是一个单峰/\这种样子的

 1 #define HAVE_STRUCT_TIMESPEC
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 long long a[500007];
 5 pair<long long,long long>stk[500007];
 6 long long l[500007],r[500007];//记录左/右边最近的比当前小的位置
 7 long long ans[500007];
 8 long long dp[5][500007];//dp[0][i]表示当a[i]在1~i上单调增时,高度的前缀和,dp[1][i]表示a[i]在i~n单调减时,高度的后缀和(单调可以平,相邻可以相等)
 9 int main(){
10     ios::sync_with_stdio(false);
11     cin.tie(NULL);
12     cout.tie(NULL);
13     int n;
14     cin>>n;
15     for(int i=1;i<=n;++i)
16         cin>>a[i];
17     int cnt=0;
18     for(int i=1;i<=n;++i){
19         if(cnt==0||stk[cnt].first<a[i])
20             stk[++cnt]=make_pair(a[i],i);
21         while(cnt>0&&stk[cnt].first>=a[i]){
22             l[stk[cnt].second]=stk[cnt-1].second;
23             r[stk[cnt].second]=i;
24             --cnt;
25         }
26         stk[++cnt]=make_pair(a[i],i);
27     }
28     while(cnt){
29         l[stk[cnt].second]=stk[cnt-1].second;
30         r[stk[cnt].second]=1+n;
31         --cnt;
32     }
33     for(int i=1;i<=n;++i)
34         if(a[i]>a[i-1])
35             dp[0][i]=dp[0][i-1]+a[i];
36         else//前面比自己大
37             dp[0][i]=dp[0][l[i]]+(i-l[i])*a[i];//找到i左边最近的比它小的,l[i]~i之间全都砍为a[l[i]]
38     for(int i=n;i;--i)
39         if(a[i]>a[i+1])
40             dp[1][i]=dp[1][i+1]+a[i];
41         else//后面比自己大
42             dp[1][i]=dp[1][r[i]]+(r[i]-i)*a[i];//找到i右边最近的比它小的,i~r[i]之间全都砍为a[r[i]]
43     long long mx=0,pos=0,now=0;
44     for(int i=1;i<=n;++i)
45         if(dp[0][i]+dp[1][i]-a[i]>mx){
46             mx=dp[0][i]+dp[1][i]-a[i];
47             pos=i;
48         }
49     ans[pos]=a[pos];
50     now=a[pos];
51     for(int i=1+pos;i<=n;++i)
52         if(a[i]>=now)
53             ans[i]=now;
54         else{
55             ans[i]=a[i];
56             now=a[i];
57         }
58     now=a[pos];
59     for(int i=pos-1;i;--i)
60         if(a[i]>=now)
61             ans[i]=now;
62         else{
63             ans[i]=a[i];
64             now=a[i];
65         }
66     for(int i=1;i<=n;++i)
67         cout<<ans[i]<<" ";
68     return 0;
69 }

猜你喜欢

转载自www.cnblogs.com/ldudxy/p/12365462.html