Codeforces Round #622 (Div. 2)C2

题意

N长度为500000以内,一个数字两边的数字不能都比他高,最多高一边

求他最大sum。叙述有问题,直接看样例

3

10 6 8

因为6左右都比他高,选择10 6 6或者6 6  8,sum明显前者高

所以答案输出10 6 6

思路:

求出每个a[i]左边(minl[i])和右边(minl[i])最近的一个比他小的数,用前缀和(suml) 和 后缀和(sumr)求得当a[i]是顶点时候sum=suml+sumr-a[i];

前缀和如果minl[i]==空集(0),那么suml[i]=i*a[i];如果minl[i]有位置,suml[i]=suml[minl[i]]+(i-minl[i])*a[i];

后缀和如果minr[i]==空集(n+1),那么sumr[i]=(n+1-i)*a[i];如果minr[i]有位置,sumr[i]=sumr[minr[i]]+(minr[i]-i)*a[i];

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define il inline
 5 #define it register int
 6 #define inf 0x3f3f3f3f
 7 #define lowbit(x) (x)&(-x)
 8 #define mem(a,b) memset(a,b,sizeof(a))
 9 #define modd 998244353
10 const int maxn=5e5+10;
11 int n;
12 ll a[maxn],b[maxn],minl[maxn],minr[maxn],suml[maxn],sumr[maxn];
13 stack<int>st;
14 int main(){
15     scanf("%d",&n);
16     for(it i=1;i<=n;i++){scanf("%lld",&a[i]);}
17     for(it i=1;i<=n;i++){
18         while(st.size()&&a[st.top()]>=a[i]){st.pop();}
19         if(st.empty()){minl[i]=0;}
20         else{minl[i]=st.top();}
21         st.push(i);
22     }
23     while(st.size()){st.pop();}
24     for(it i=n;i>=1;i--){
25         while(st.size()&&a[st.top()]>=a[i]){st.pop();}
26         if(st.empty()){minr[i]=n+1;}
27         else{minr[i]=st.top();}
28         st.push(i);
29     }
30     for(it i=1;i<=n;i++){
31         if(!minl[i]){suml[i]=(ll)i*a[i];}
32         else{
33             suml[i]=suml[minl[i]]+(ll)(i-minl[i])*a[i];
34         }
35     }
36     for(it i=n;i>=1;i--){
37         if(minr[i]==n+1){sumr[i]=(ll)(minr[i]-i)*a[i];}
38         else{
39             sumr[i]=sumr[minr[i]]+(ll)(minr[i]-i)*a[i];
40         }
41     }
42     ll ans=-1;int pos;
43     for(it i=1;i<=n;i++){
44         ll zz=sumr[i]+suml[i]-a[i];
45         //cout<<sumr[i]<<" "<<minr[i]<<" "<<suml[i]<<endl;
46         if(zz>ans){
47             ans=zz,pos=i;
48         }
49     }
50
51     b[pos]=a[pos];ll zhi=a[pos];
52     for(it i=pos+1;i<=n;i++){
53         if(a[i]<zhi){
54             zhi=a[i];
55         }
56         b[i]=zhi;
57     }
58     zhi=a[pos];
59     for(it i=pos-1;i>0;i--){
60         if(a[i]<zhi){
61             zhi=a[i];
62         }
63         b[i]=zhi;
64     }
65     for(it i=1;i<=n;i++){
66         printf(i==n?"%lld\n":"%lld ",b[i]);
67     }
68     return 0;
69 }

原文地址:https://www.cnblogs.com/luoyugongxi/p/12356639.html

时间: 2024-08-30 09:42:07

Codeforces Round #622 (Div. 2)C2的相关文章

[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 #622 (Div. 2)C2 Skyscrapers最大&quot;尖&quot;性矩形,思维

题:https://codeforces.com/contest/1313/problem/C2 题意:给出n个数,分别代表第i个位置所能搭建的最大高度,问以哪一个位置的塔的高度为基准向左的每一个塔都小于等于临近右边的塔,向右每一个塔都大于等于临近的左边的塔所构建的高度之和是最大的,输出最大的高度之和: 分析:我们设一个fir[i]数组,表示当前 i 位置向左能构造的最大高度和(就想阶梯一样,i位置是阶梯的最高处),sec[i]则是向右的: 因为求出这俩个数组后,我们直接o(n)的访问fir[i

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

题目链接:http://codeforces.com/contest/1313/problem/C2 题意:有n个房子,每个房子可以建的最高层数为a[i],但不可以出现相邻左右两边房子的层数都比中间高的情况,要求总共层数要尽可能的多,输出每个房子应该建几层. 思路:记录左边比自己小的第一个元素,同时可以求出当i为顶端是的前缀和.然后记录右边第一个比自己小的元素,同时可以求出当i为顶端是的后缀和.然后再遍历一篇,看谁为顶端时,总层数最多,最后再依次确定层数即可. #include<stdio.h>

Codeforces Round # 555 (Div. 3) C2. Increasing subsequence (complicated version) (贪心)

题目链接:http://codeforces.com/contest/1157/problem/C2 当左右两边数字相同时,需要判断一下取哪边能得到更长的递增序列 #include <iostream> #include <cstring> #include <algorithm> #include <cmath> #include <cstdio> #include <queue> #include <climits>

Codeforces Round #622 (Div. 2)

A: 题意: 有ABC的三种菜,现在有a个A,b个B,c个C,问能组成多少种不同菜单 思路: abc都大于等于4,肯定是7种,给abc排个序,从大到小举例删减 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define il inline 5 #define it register int 6 #define inf 0x3f3f3f3f 7 #define lowbit(x) (x)&am

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 l

Codeforces Round #315 (Div. 1)

A. Primes or Palindromes? time limit per test 3 seconds memory limit per test 256 megabytes input standard input output standard output Rikhail Mubinchik believes that the current definition of prime numbers is obsolete as they are too complex and un