Codeforces Round #622 (Div. 2)C2 Skyscrapers最大"尖"性矩形,思维||分治
题:https://codeforces.com/contest/1313/problem/C2
题意:给出n个数,分别代表第i个位置所能搭建的最大高度,问以哪一个位置的塔的高度为基准向左的每一个塔都小于等于临近右边的塔,向右每一个塔都大于等于临近的左边的塔所构建的高度之和是最大的,输出最大的高度之和;
分析:我们设一个fir[i]数组,表示当前 i 位置向左能构造的最大高度和(就想阶梯一样,i位置是阶梯的最高处),sec[i]则是向右的;
因为求出这俩个数组后,我们直接o(n)的访问fir[i]+sec[i]-a[i]找最大的既可找出能构造出最大面积和的位置;
对于这个fir[]的求法,对于位置 i ,可以利用前面已经算得的结果,假设位置 j (j<i)很明显的fir[i]=fir[j]+(i-j)*a[i],因为再i~j间的高度都是大于a[i]的,fir[i]是取不到fir[i~j]间的部分面积的,所以把i~j高度降为和 i 位置的高度一样即可贪心地求最大,sec[]求法类似
#include<bits/stdc++.h>
using namespace std;
const int M=5e5+;
typedef long long ll;
ll a[M],pre[M],las[M],s[M],fir[M],sec[M],ans[M];
int main(){
ios::sync_with_stdio(false);
cin.tie();
int n,top=;
cin>>n;
for(int i=;i<=n;i++)
cin>>a[i];
for(int i=;i<=n;i++){
while(top&&a[i]<a[s[top]])
top--;
pre[i]=s[top];
s[++top]=i;
fir[i]=fir[pre[i]]+1ll*(i-pre[i])*a[i];
}
s[top=]=n+;
for(int i=n;i>=;i--){
while(top&&a[i]<a[s[top]])
top--;
las[i]=s[top];
s[++top]=i;
sec[i]=sec[las[i]]+1ll*(las[i]-i)*a[i];
}
int pos=;
for(int i=;i<=n;i++){
if(fir[i]+sec[i]-a[i]>fir[pos]+sec[pos]-a[pos])
pos=i;
}
for(int i=pos;i;i=pre[i])
for(int j=i;j>pre[i];j--)
ans[j]=a[i];
for(int i=pos;i;i=las[i])
for(int j=i;j<las[i];j++)
ans[j]=a[i];
for(int i=;i<=n;i++)
cout<<ans[i]<<' ';
return ;
}
分治做法:
分析:对于任意一段[l,r]的高度限制,假设a[i]是其中最小的高度,那么 要么是 i 的右边的高度全设为a[i],要么 i 的左边的高度全设为a[i]这俩种可能,那我们就分治下这些区间就行了;
找最小的高度用线段树实现即可,也可用其他方法;
复杂度分析,退化的情况我们分治的区间是[1,n],[1,n-1],[1,n-2]。。。这样n个区间,那么只要我们保证每个区间只是log级别的复杂度即可;
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define lson root<<1,l,midd
#define rson root<<1|1,midd+1,r
typedef long long ll;
const int inf=0x3f3f3f3f;
const int M=5e5+;
int n;
struct node{
ll val,id;
}tr[M<<];
ll a[M],ans[M];
void up(int root){
if(tr[root<<].val<=tr[root<<|].val){
tr[root]=tr[root<<];
}
else
tr[root]=tr[root<<|];
}
void build(int root,int l,int r){
if(l==r){
tr[root].val=a[l];
tr[root].id=l;
return ;
}
int midd=(l+r)>>;
build(lson);
build(rson);
up(root);
}
node query(int L,int R,int root,int l,int r){
if(L<=l&&r<=R){
return tr[root];
}
node res;
res.val=1e9+;
int midd=(l+r)>>;
if(L<=midd){
node now=query(L,R,lson);
if(now.val<res.val)
res=now;
}
if(R>midd){
node now=query(L,R,rson);
if(now.val<res.val)
res=now;
}
return res;
}
ll solve(int l,int r){
// cout<<l<<"!!"<<r<<endl;
if(l>r)
return 0ll;
if(l==r){
ans[l]=a[l];
return a[l];
}
node now=query(l,r,,,n);
// cout<<now.id<<"!!"<<endl;
ll lsum=solve(l,now.id-);
ll rsum=solve(now.id+,r);
if(lsum+now.val+1ll*now.val*(r-now.id)>1ll*now.val*(now.id-l)+now.val+rsum){
for(int i=now.id;i<=r;i++)
ans[i]=now.val;
return lsum+now.val+now.val*(r-now.id);
}
else{
for(int i=l;i<=now.id;i++)
ans[i]=now.val;
return now.val*(now.id-l)+now.val+rsum;
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie();
cin>>n;
for(int i=;i<=*n;i++)
tr[i].val=inf;
for(int i=;i<=n;i++)
cin>>a[i];
build(,,n); solve(,n);
for(int i=;i<=n;i++)
cout<<ans[i]<<' ';
return ;
}
Codeforces Round #622 (Div. 2)C2 Skyscrapers最大"尖"性矩形,思维||分治的更多相关文章
- 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)
第二次写题解,请多多指教! 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)
题目链接: C1. Skyscrapers (easy version) 题目描述: 有一行数,使得整个序列满足 先递增在递减(或者只递增,或者只递减) ,每个位置上的数可以改变,但是最大不能超过原来 ...
- 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 ...
- Codeforces Round #622 (Div. 2)C2
题意 N长度为500000以内,一个数字两边的数字不能都比他高,最多高一边 求他最大sum.叙述有问题,直接看样例 3 10 6 8 因为6左右都比他高,选择10 6 6或者6 6 8,sum明显前 ...
- 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 #529 (Div. 3) E. Almost Regular Bracket Sequence (思维)
Codeforces Round #529 (Div. 3) 题目传送门 题意: 给你由左右括号组成的字符串,问你有多少处括号翻转过来是合法的序列 思路: 这么考虑: 如果是左括号 1)整个序列左括号 ...
随机推荐
- 腾讯X5内核使用详解(X5内核播放器使用如何去除控制栏全屏播放)以及一些注意事项
例子下载地址 https://www.lanzous.com/i2zsv5g GIT就不用了麻烦的不行 本人安卓刚学 就上X5内核弄了老长时间由于对maven 和idea不熟悉刚开始导包都是 ...
- TS文件极简合并
TS文件是可以直接通过二进制拷贝连接的方式进行合并的,一般采用如下的命令行参数:copy /b 1.ts+2.ts+3.ts new.ts 这个例子就是将1.ts.2.ts.3.ts三个文件按顺序连接 ...
- UVA - 1152 4 Values whose Sum is 0(中途相遇法)
题意:从四个集合各选一个数,使和等于0,问有多少种选法. 分析:求出来所有ai + bi,在里面找所有等于ci + di的个数. #pragma comment(linker, "/STAC ...
- linux下安装mysql5.7(centos6.0)
注:因为网络原因,这个mysql安装是我以前在学校的时候找到的一个安装包,不过也找到了下载的地址:http://www.itmop.com/downinfo/143061.html下载完成后,把文件上 ...
- linux下安装jdk&&Tomcat环境
linux系统 Centos6 下部署应用服务 jdk-1.7 环境安装:(切换到root用户下操作)1. 在 /usr/local 目录下创建jdk7文件 mkdir /usr/local/jdk7 ...
- 留学英文论文写作Abstract三种类型
所谓Abstract,就是对所写论文主要内容的精炼概括.Abstract是美国人的说法,英国的科技期刊喜欢称之为Summary.在英文中,有资料是这么对其定义的:Abstract is a sketc ...
- hdu 2583 How far away ? 离线算法 带权求最近距离
How far away ? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- 【剑指Offer】面试题07. 重建二叉树
题目 输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字. 例如,给出 前序遍历 preorder = [3,9,20,15,7] 中序遍历 ...
- P2057 [SHOI2007]善意的投票 / [JLOI2010]冠军调查
P2057 [SHOI2007]善意的投票 / [JLOI2010]冠军调查 拿来练网络流的qwq 思路:如果i不同意,连边(i,t,1),否则连边(s,i,1).好朋友x,y间连边(x,y,1)(y ...
- TX2开发板Ubuntu16.04安装中文输入法
打开终端输入安装输入法: sudo apt-get install fcitx fcitx-googlepinyin fcitx-module-cloudpinyin fcitx-sunpinyin ...