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)整个序列左括号 ...
随机推荐
- python 文件夹递归
import ospath = "F:/new" #文件夹目录datas = []def eachFile(filepath): fileNames = os.listdir(fi ...
- spring boot 接口service有多个实现类
接口.java public interface DeService { } 接口实现类1.java @Service("ud")public class DeServiceImp ...
- Window Server 2019 配置篇(1)- 创建域并把本机设置成域控制器
由于这个学期的Window Server大作业是做一个服务器群,在域中创建包括DNS,DHCP,网关,更新服务器,hyper-v,自动部署等服务,所以我会把制作过程分步写在这个博客上 首先我们新建一个 ...
- 关于SSM中mybatis向oracle添加语句采用序列自增的问题
在SSM向oracle数据库中插入语句时,报错如下: ### Error updating database. Cause: java.sql.SQLException: 不支持的特性 ### SQ ...
- CharacterEncodingFilter这个spring的过滤器
org.springframework.web.filter.CharacterEncodingFilter 对请求于响应的编码进行过滤,半路出家的和尚总是对什么都感觉到好奇,都想记录下来(
- 五十一、SAP中使程序结构化,模块化
一.我们创建3个引用单元,这3个单元里面分别存放定义相关,执行相关和子程序相关的内容 二.将程序中的各部分都拆分到INCLUDE文件中,DEF文件内容如下 三.INC文件内容 四.MAIN文件中写程序 ...
- redis在.Net程序中使用
1.设置访问密码 config 2.连接redis服务器 private static string redisHost = ConfigHelper.GetAppSetting("redi ...
- chrome浏览器安装vue调试器vue-devtools
chrome浏览器安装vue调试器vue-devtools https://blog.csdn.net/zhangjnwei/article/details/76693053
- UVA - 12107 Digit Puzzle(数字谜)(IDA*)
题意:给出一个数字谜,要求修改尽量少的数,使修改后的数字谜只有唯一解.空格和数字可以随意替换,但不能增删,数字谜中所有涉及的数必须是没有前导零的正数.输入数字谜一定形如a*b=c,其中a.b.c分别最 ...
- linux下的 sudo ln -s 源文件 目标文件
这是linux中一个非常重要命令,请大家一定要熟悉.它的功能是为某一个文件或目录在另外一个位置建立一个同步的链接,类似Windows下的超级链接. 这个命令最常用的参数是-s,具体用法是:sudo l ...