题目链接 :

C2. Skyscrapers (hard version)

题目描述 :

与上一道题类似,只是数据范围变大, 5e5, 如果用我们原来的方法,铁定是超时的。

考察点 :

单调栈,贪心,前缀和,后缀和

析题得侃:

上面说了,用原先得方法得话是铁定超时的,那怎么优化呢?通过 easy version ,我们可以
得知合适的位置一定是由两部分组成的,左侧的数的和,右侧的数的和,我们求这些和的时候
也确实浪费了大量的时间,我们能否知道这个位置,然后直接得到这个位置的和呢?然后直接
取一下最大值。
我们知道左右两侧一定是单调的,那么既然是单调的,我们能不能用单调栈来维护呢?
显然是可以的。
怎么维护呢?
看一组数据 :
下标 : 1 2 3 4 5 6
数值 : 5 2 3 6 7 4 (假设现在都在左侧,还没有找到合适的中间位置)
我们发现 2 的左侧必须 <= 2,同样的, 4 的左侧必须 <= 4,但是 有些数本来就比 4 小
所以 pre[6] = pre[3] + a[6] * (6 - 3)
同理,后缀也是一样的,逆过来就可以了
接下来我们要求某个位置的和就是 : sum = pre[i] + suf[i + 1]

Code:

#include <stack>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; const int maxn = 5e5 + 10; typedef long long LL; LL a[maxn],pre[maxn],suf[maxn];
LL L[maxn],R[maxn]; int n; stack<int>S; int main(void) {
scanf("%d",&n);
for(int i = 1; i <= n; i ++) {
scanf("%lld",&a[i]);
}
// 便于我们处理,可以先入栈一个 0
S.push(0);
for(int i = 1; i <= n; i ++) {
while(a[i] <= a[S.top()]) S.pop();
L[i] = S.top();
S.push(i);
}
while(!S.empty()) S.pop();
//同上
S.push(n + 1);
for(int i = n; i ; i --) {
while(a[i] <= a[S.top()]) S.pop();
R[i] = S.top();
S.push(i);
}
//计算每个位置的前缀和
for(int i = 1; i <= n; i ++) {
LL l = L[i];
pre[i] = pre[l] + a[i] * (i - l);
}
//计算每个位置的后缀和
for(int j = n; j ; j --) {
LL r = R[j];
suf[j] = suf[r] + a[j] * (r - j);
}
// 寻找合适的位置
LL sum = pre[1] + suf[2],id = 1;
for(int i = 1; i <= n; i ++ ) {
if(sum < pre[i] + suf[i + 1]) {
id = i;
sum = pre[i] + suf[i + 1];
}
}
for(int i = id - 1; i >= 1; i --) {
a[i] = min(a[i + 1],a[i]);
}
// 中间的那两个位置一定是 ok 的,我们需要从下一个开始
for(int j = id + 2; j <= n; j ++) {
a[j] = min(a[j - 1],a[j]);
}
for(int i = 1; i <= n; i ++) {
cout << a[i] << " ";
}
cout << endl;
return 0;
}

后记 :

优化往往是再复杂的基础上进行优化,根据某些性质,利用相应的数据结构进行优化。

Codeforces Round #622(Div 2)C2. Skyscrapers (hard version)的更多相关文章

  1. Codeforces Round #581(Div. 2)

    Codeforces Round #581(Div. 2) CF 1204 A. BowWow and the Timetable 题解:发现,$4$的幂次的二进制就是一个$1$后面跟偶数个$0$. ...

  2. Codeforces Round #334(div.2)(新增不用二分代码) B

    B. More Cowbell time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...

  3. Codeforces Round #334(div.2) A

    A. Uncowed Forces time limit per test 1 second memory limit per test 256 megabytes input standard in ...

  4. codeforces Round #389(Div.2)C Santa Claus and Robot(思维题)

    题目链接:http://codeforces.com/contest/752/problem/C 题意:给出一系列机器人的行动方向(机器人会走任意一条最短路径),问最少标记几个点能让机器人按这个 路径 ...

  5. Codeforces Round #626 (Div. 2) B. Count Subrectangles

    题目连接:https://codeforces.com/contest/1323/problem/B 题意:给一个大小为n的a数组,一个大小为m的b数组,c数组是二维数组c[i][j]=a[i]*b[ ...

  6. Codeforces Round #342 (Div 2) 解题报告

    除夕夜之有生之年CF第一场 下午从奶奶家回到姥姥家,一看还有些时间,先吃点水果陪姥姥姥爷聊了会儿,再一看表,5:20....woc已经开场20分钟了...于是抓紧时间乱搞.. **A. Guest F ...

  7. Codeforces Round 1153(div. 2)

    这场奇差.ABCD四题.179名. 但是E在现场有213个人做出. 描述一下我在35分钟做完D后的心路历程. 首先看到这道E,第一下想到的是把所有的横向和竖向的整列(行)求出相连的个数. 然后想如何能 ...

  8. Codeforces Round #345 (Div 2)

    最后两题是orzCJK学长帮忙代打的,不过总算是到蓝名了(上次睡迟了,只剩半个小时,结果作大死点开题目看,结果rating掉了100多),还有论代码风格的重要性!!!(没写空格被学长各种D) A题 题 ...

  9. Codeforces Round #556(Div.1)

    A 容易发现i,i+1至少有一个数出现,于是可以让尽量多的2和奇数出现 #include<bits/stdc++.h> using namespace std; int n,s1,s2; ...

随机推荐

  1. 简单处理IP XML数据

    ///* 编译环境: visual c++ */ //#include <stdio.h> //#include <winsock2.h> //#pragma comment( ...

  2. Codeforces_794

    A.统计两个guard之间的钞票数. #include<bits/stdc++.h> #define MOD 1000000009 using namespace std; int a,b ...

  3. LeetCode22 生成所有括号对

    本文始发于个人公众号:TechFlow,原创不易,求个关注 链接 Generate Parentheses 难度 Medium 描述 Given n pairs of parentheses, wri ...

  4. java10幸运抽奖

    public class jh_01_知识点回顾 { public static void main(String[] args) { int a = 10; // 变量.标签. // 重新给a赋值. ...

  5. Grafana & Graphite & Collectd:监控系统

    简介 监控是运维工作中的一个重要组成部分,今天介绍一套新的监控工具,方便好用,扩展性强,这套工具有三个组件,Grafana & Graphite & Collectd: Grafana ...

  6. Go语言实现:【剑指offer】不用加减乘除做加法

    该题目来源于牛客网<剑指offer>专题. 第一步:相加各位的值,不算进位,得到010,二进制每位相加就相当于各位做异或操作,101^111. 第二步:计算进位值,得到1010,相当于各位 ...

  7. 【Debian】 Debian 安装源配置

    Debian 安装源配置 所有的Linux安装完后第一件事,就是要更新安装源 安装源是什么呢,安装源又称软件源,是指把软件的安装源地址放在一个pool里面,用一条命令(比如apt-get instal ...

  8. linux 删除文件 磁盘空间未释放

    具体情况就是:删除了一个超大文件后,发现磁盘空间没有变化 原因:有进程正在使用这个文件,虽然我们从文件系统的目录结构上解除链接(unlink),然而文件是被 打开的(有一个进程正在使用),那么进程将仍 ...

  9. [Linux]命令返回值以及错误对照表

    Linux执行完命令之后默认会有一个返回值 # ls app backupconfig.json Doc manage.py __pycache__ settings.py # echo $? 0 错 ...

  10. 一起了解 .Net Foundation 项目 No.7

    .Net 基金会中包含有很多优秀的项目,今天就和笔者一起了解一下其中的一些优秀作品吧. 中文介绍 中文介绍内容翻译自英文介绍,主要采用意译.如与原文存在出入,请以原文为准. Entity Framew ...