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)整个序列左括号 ...
随机推荐
- gitolite服务器配置的一些心得
1.假设说有服务器1,hostname为lab1,服务器2,hostname为lab2,分别生成的给对方使用的公钥为server-lab1.pub.server-lab2.pub,服务器1和2都有自己 ...
- java se
集群 数据库集群.服务器集群.内存 java特性 封装:封装细节和封装变化(可能发生需求变更的代码必须要封装,set方法除了完成赋值功能外,还能处理额外的任务,记录访问的人) 继承 多态 访问限定符 ...
- Git提交出现error: src refspec master does not match any的问题
在本地与远程分别新建了一个仓库并且关联后,想要把本地的文件提交到github上面, 输入下方命令后没有成功,而是出现了报错:error: src refspec master does not mat ...
- Bulma CSS - 简介
Bulma CSS框架教程 Bulma CSS – 简介 Bulma CSS – 开始 Bulma CSS – CSS类 Bulma CSS – 模块化 Bulma CSS – 响应式 Bulma是什 ...
- 解决Tomcat在idea控制台乱码问题
解决Tomcat乱码问题 打开Tomcat安装目录:apache-tomcat-9.0.14-windows-x64/conf/logging.properties 大概在50多行注释这一句#java ...
- js库链接
1.autoHeightTextarea自适应高度的textarea是一款jquery插件,支持链式调用,支持设置最小行数.最小高度.最大行数和最大高度,在输入文字的时候实现textarea的高度自适 ...
- Sublime Text基本配置
官网最新版本号 3059 破解链接: http://bbs.pediy.com/showthread.php?t=182774 可以看那个人放出来的百度网盘,去他的百度网盘里面可以看到最新的破解文件. ...
- UVA 11992 懒惰标记应用
这个题目要求和 还有 设置区间值 区间增值,明显要用线段树来 由于行数不超过20 而列数多达 10^5,所以对每一行建一棵线段树. 然后主要是在懒惰标记方面是难点 针对两种操作 分别设置 set 和 ...
- /Array.CreateInstance创建类型为int,长度为5的数组
using System;using System.Collections.Generic;using System.Linq;using System.Text; namespace Console ...
- ACM&OI 基础数论算法专题
ACM&OI 基础数学算法专题 一.数论基础 质数及其判法 (已完结) 质数的两种筛法 (已完结) 算数基本定理与质因数分解 (已完结) 约数与整除 (已完结) 整除分块 (已完结) 最大公约 ...