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 }

原文地址:https://www.cnblogs.com/ldudxy/p/12365462.html

时间: 2024-07-30 14:02:52

Codeforces Round #622 (Div. 2)C(单调栈,DP)的相关文章

[Codeforces Round #622 (Div. 2)] - C2. Skyscrapers (hard version) (单调栈)

[Codeforces Round #622 (Div. 2)] - C2. Skyscrapers (hard version) (单调栈) C2. Skyscrapers (hard version) time limit per test 3 seconds memory limit per test 512 megabytes input standard input output standard output This is a harder version of the probl

Codeforces Round #622 (Div. 2) C2. Skyscrapers (hard version) 单调栈

Codeforces Round #622 (Div. 2) C2. Skyscrapers (hard version) 问题 传送门 我是参考了这篇题解传送门,然后按着思路做出了的(但大佬题解中的sumr[]数组操作我没看懂,然后自己改了改). 摘抄: 维护峰值最优 找左右边的第一个比自己小的元素,维护前缀和,找最大的峰值 l[i]:用单调栈维护左边第一个比它小的数 r[i]:用单调栈维护右边第一个比它小的数 suml[i]:左边的前缀和 sumr[i]:右边的前缀和 然后遍历一遍数组,找到

Codeforces Round #622 (Div. 2) C2. Skyscrapers (hard version)(单调栈,递推)

Codeforces Round #622 (Div. 2) C2. Skyscrapers (hard version) 题意: 你是一名建筑工程师,现给出 n 幢建筑的预计建设高度,你想建成峰状,如: 1 2 3 2 1 → 1 2 3 2 1 1 2 3 1 2 → 1 2 3 1 1 8 10 6 → 8 10 6 10 6 8 → 10 6 6 问所有建筑的高度和最大为多少. 思路: 单调递增栈栈顶存储以当前点为峰的单侧最低高度下标,另存储以每个点为峰的左右最大高度和. #includ

Codeforces Round #260 (Div. 1) A. Boredom (DP)

题目链接:http://codeforces.com/problemset/problem/455/A A. Boredom time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Alex doesn't like boredom. That's why whenever he gets bored, he comes up with

Codeforces Round #424 (Div. 2) D. Office Keys(dp)

题目链接:Codeforces Round #424 (Div. 2) D. Office Keys 题意: 在一条轴上有n个人,和m个钥匙,门在s位置. 现在每个人走单位距离需要单位时间. 每个钥匙只能被一个人拿. 求全部的人拿到钥匙并且走到门的最短时间. 题解: 显然没有交叉的情况,因为如果交叉的话可能不是最优解. 然后考虑dp[i][j]表示第i个人拿了第j把钥匙,然后 dp[i][j]=max(val(i,j),min(dp[i-1][i-1~j]))   val(i,j)表示第i个人拿

Codeforces Round #369 (Div. 2) C. Coloring Trees(dp)

题目链接:Codeforces Round #369 (Div. 2) C. Coloring Trees 题意: 有n个树,每个树有一个颜色,如果颜色值为0,表示没有颜色,一共有m个颜色,第j种颜色涂第i棵树需要花费pij,颜色一样且相邻的分为一组 现在要将所有颜色为0的树涂上颜色,使得这些树恰好可以分为k组,问最小的花费 题解: 考虑dp[i][j][k],表示考虑第i棵树涂第j种颜色,当前分为k组的最小花费,然后状态转移看代码,注意的是dp的初始状态 1 #include<bits/std

Codeforces Round #455 (Div. 2) C. Python Indentation dp递推

Codeforces Round #455 (Div. 2) C. Python Indentation 题意:python 里面,给出 n 个 for 循环或陈述语句,'f' 里面必须要有语句.按 python 缩进的方式组合成合法的程序,问有多少种可能方案. tags: dp dp[i][j] 表示第 i 个语句缩进为 j 时的可能方案数, 转移: 1] 如果第 i 个是 'f' , 则第 i+1 个肯定要比第 i 个多缩进一个单位,即 dp[i+1][j] = dp[i][j]. 2]如果

Educational Codeforces Round 23 D. Imbalanced Array(单调栈)

题目链接:Educational Codeforces Round 23 D. Imbalanced Array 题意: 给你n个数,定义一个区间的不平衡因子为该区间最大值-最小值. 然后问你这n个数所有的区间的不平衡因子和 题解: 对每一个数算贡献,a[i]的贡献为 当a[i]为最大值时的 a[i]*(i-l+1)*(r-i+1) - 当a[i]为最小值时的a[i]*(i-l+1)*(r-i+1). 计算a[i]的l和r时,用单调栈维护.具体看代码,模拟一下就知道了. 然后把所有的贡献加起来.

Codeforces Round #527 (Div. 3)D2(栈,思维)

#include<bits/stdc++.h>using namespace std;int a[200007];stack<int>s;int main(){    int n;    int mn=0;    scanf("%d",&n);    for(int i=1;i<=n;i++){        scanf("%d",&a[i]);        if(a[i]>mn)            mn=a