Codeforces Round #622 C2.Skyscrapers (hard version)
This is a harder version of the problem. In this version n≤500000n≤500000
The outskirts of the capital are being actively built up in Berland. The company "Kernel Panic" manages the construction of a residential complex of skyscrapers in New Berlskva. All skyscrapers are built along the highway. It is known that the company has already bought nn plots along the highway and is preparing to build nn skyscrapers, one skyscraper per plot.
Architects must consider several requirements when planning a skyscraper. Firstly, since the land on each plot has different properties, each skyscraper has a limit on the largest number of floors it can have. Secondly, according to the design code of the city, it is unacceptable for a skyscraper to simultaneously have higher skyscrapers both to the left and to the right of it.
Formally, let's number the plots from 11 to nn . Then if the skyscraper on the ii -th plot has aiai floors, it must hold that aiai is at most mimi (1≤ai≤mi1≤ai≤mi ). Also there mustn't be integers jj and kk such that j<i<kj<i<k and aj>ai<akaj>ai<ak . Plots jj and kk are not required to be adjacent to ii .
The company wants the total number of floors in the built skyscrapers to be as large as possible. Help it to choose the number of floors for each skyscraper in an optimal way, i.e. in such a way that all requirements are fulfilled, and among all such construction plans choose any plan with the maximum possible total number of floors.
Input
The first line contains a single integer nn (1≤n≤5000001≤n≤500000 ) — the number of plots.
The second line contains the integers m1,m2,…,mnm1,m2,…,mn (1≤mi≤1091≤mi≤109 ) — the limit on the number of floors for every possible number of floors for a skyscraper on each plot.
Output
Print nn integers aiai — the number of floors in the plan for each skyscraper, such that all requirements are met, and the total number of floors in all skyscrapers is the maximum possible.
If there are multiple answers possible, print any of them.
Examples
5
1 2 3 2 1
1 2 3 2 1
3
10 6 8
10 6 6
Note
In the first example, you can build all skyscrapers with the highest possible height.
In the second test example, you cannot give the maximum height to all skyscrapers as this violates the design code restriction. The answer [10,6,6][10,6,6] is optimal. Note that the answer of [6,6,8][6,6,8] also satisfies all restrictions, but is not optimal.
看到5e6的数据规模肯定不能O(n^2)暴力了,可以考虑单调栈。首先求出每个位置的最大左侧非递减序列和并存储到up[i](包括自己),可以用一个单调栈来维护。同理求出每个位置的最大右侧非递增序列和存到down[i],复杂度都为O(n).然后枚举每个位置,统计up[i]+down[i]-a[i](重复加了a[i],要减去一个),找到最大的一个位置往两边构造即可。注意这里单调栈的写法,我一开始直接用数组元素往里push,维护单调性时复杂度就可能很高,在第九个点T了...最后学习https://blog.csdn.net/weixin_44164153/article/details/104486676?fps=1&locationNum=2博客里的写法,改用数组下标往栈里push就能过了。
#include <bits/stdc++.h>
using namespace std;
long long a[],up[]={},down[]={},out[]={};//up[i]表示包括i最大非递减序列的和 比较up[i]+down[i]-a[i]即可(减去一个重复的)
int n;
int main()
{
cin>>n;
int i,j,k;
for(i=;i<=n;i++)scanf("%d",&a[i]);
stack<int>s;
s.push();
for(i=;i<=n;i++)
{
// if(a[i]>s.top())
// {
// up[i]=up[i-1]+a[i];
// //s.push(a[i]);
// s.push(i);
// }
// else
// {
// long long cnt=0,tot=0;
// while(s.size()&&s.top()>a[i])
// {
// tot+=s.top();
// cnt++;
// s.pop();
// }
// for(j=1;j<=cnt+1;j++)//出去的个数加上新进来的一个
// {
// s.push(a[i]);1
// }
// up[i]=a[i]*(cnt+1)+up[i-1]-tot;
while(s.size()&&a[s.top()]>=a[i])
{
s.pop();
}
up[i]=up[s.top()]+(i-s.top())*a[i];//有跨越的直接乘a[i]加过去即可
s.push(i);
// }
}
while(s.size())s.pop();
s.push(n+);//占位
for(i=n;i>=;i--)
{
// if(a[i]>s.top())
// {
// down[i]=down[i+1]+a[i];
// //s.push(a[i]);
// s.push(i);
// }
// else
// {
// long long cnt=0,tot=0;
// while(s.size()&&s.top()>a[i])
// {
// tot+=s.top();
// cnt++;
// s.pop();
// }
// for(j=1;j<=cnt+1;j++)//出去的个数加上新进来的一个
// {
// s.push(a[i]);
// }
// down[i]=a[i]*(cnt+1)+down[i+1]-tot;
while(s.size()&&a[s.top()]>=a[i])
{
s.pop();
}
down[i]=down[s.top()]+(s.top()-i)*a[i];
s.push(i);
// }
}
long long ans=,num=;
for(i=;i<=n;i++)
{
if(up[i]+down[i]-a[i]>ans)
{
ans=up[i]+down[i]-a[i];
num=i;
}
}
//构造输出序列
out[num]=a[num];
for(j=num-;j>=;j--)
{
out[j]=min(a[j],out[j+]);
}
for(j=num+;j<=n;j++)
{
out[j]=min(a[j],out[j-]);
}
for(i=;i<=n;i++)
{
cout<<out[i]<<' ';
}
return ;
}
Codeforces Round #622 C2.Skyscrapers (hard version)的更多相关文章
- Codeforces Round #622 (Div. 2) C2. Skyscrapers (hard version)(单调栈,递推)
Codeforces Round #622 (Div. 2) C2. Skyscrapers (hard version) 题意: 你是一名建筑工程师,现给出 n 幢建筑的预计建设高度,你想建成峰状, ...
- Codeforces Round #622(Div 2)C2. Skyscrapers (hard version)
题目链接 : C2. Skyscrapers (hard version) 题目描述 : 与上一道题类似,只是数据范围变大, 5e5, 如果用我们原来的方法,铁定是超时的. 考察点 : 单调栈,贪心, ...
- Codeforces Round #622 (Div. 2) B. Different Rules(数学)
Codeforces Round #622 (Div. 2) B. Different Rules 题意: 你在参加一个比赛,最终按两场分赛的排名之和排名,每场分赛中不存在名次并列,给出参赛人数 n ...
- Codeforces Round #622 (Div. 2) A. Fast Food Restaurant(全排列,DFS)
Codeforces Round #622 (Div. 2) A. Fast Food Restaurant 题意: 你是餐馆老板,虽然只会做三道菜,上菜时还有个怪癖:一位客人至少上一道菜,且一种菜最 ...
- Codeforces Round #622(Div 2) C1. Skyscrapers (easy version)
题目链接: C1. Skyscrapers (easy version) 题目描述: 有一行数,使得整个序列满足 先递增在递减(或者只递增,或者只递减) ,每个位置上的数可以改变,但是最大不能超过原来 ...
- Codeforces Round #622 (Div. 2) 1313 C1
C1. Skyscrapers (easy version) time limit per test1 second memory limit per test512 megabytes inputs ...
- Codeforces Round #622 (Div. 2).C2 - Skyscrapers (hard version)
第二次写题解,请多多指教! http://codeforces.com/contest/1313/problem/C2 题目链接 不同于简单版本的暴力法,这个数据范围扩充到了五十万.所以考虑用单调栈的 ...
- Codeforces Round #622 (Div. 2) C2 - Skyscrapers (hard version) 单调栈
从左往右扫,找到比第i个小的第一个数字,l[i] = l[last] + (i - last) * m[i],用单调栈O(n)维护这个过程,再从右往左扫,同理可以算出r数组,注意一下long long ...
- Codeforces Round #622 (Div. 2) C1. Skyscrapers (easy version)(简单版本暴力)
This is an easier version of the problem. In this version n≤1000n≤1000 The outskirts of the capital ...
随机推荐
- 【剑指Offer】44、翻转单词顺序列
题目描述 牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上.同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思.例如,“student ...
- AspxGridView 客户端点击获取对应的列值
Html 内容: <dx:ASPxGridView ID="ASPxGridViewCluster" runat="server" Width=" ...
- sql 分组后查询出排序字段
select row_number() over(partition by CODE order by SEQUENCE) as RowIndex from Table 注:根据表的CODE 字 ...
- Vue快速认识
1.Vue入门初识 1.1 Vue.js是什么? 一位华裔前Google工程师(尤雨溪)开发的前端js库 作用: 动态构建用户界面 特点: 遵循MVVM模式 编码简洁, 体积小, 运行效率高, 移动/ ...
- android 直接添加一个Fragment到activity,不需要额外setContentView
getSupportFragmentManager().beginTransaction().replace(android.R.id.content,new ArticleListFragment( ...
- jQuery-File-Upload 使用,jQuery-File-Upload上传插件
================================ ©Copyright 蕃薯耀 2020-01-10 https://www.cnblogs.com/fanshuyao/ 一.官网地址 ...
- Go键盘输入与打印输出
输出 格式化打印占位符 符号 说明 %v 默认格式 %T 打印类型 %t 布尔类型 %s 字符串 %f 浮点数 %d 十进制的整数 %b 二进制的整数 %o 八进制 %x 十六进制0-9 a-f %X ...
- 洛谷P1582 倒水 二进制的相关应用
https://www.luogu.org/problem/P1582 #include<bits/stdc++.h> using namespace std; long long N,K ...
- Java 散列集笔记
散列表 散列表(hash table)为每个对象计算一个整数,称为散列码(hash code). 若需要自定义类,就要负责实现这个类的hashCode方法.注意自己实现的hashCode方法应该与eq ...
- Python之路Day06
小数据池 == 判断两个值是否相等 is -- 是,判断两边的内存地址是否相同 a=10 b=10 print(a is b) id() -- 查看内存地址 代码块 一个py文件,一个函数,一个模块, ...