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)整个序列左括号 ...
随机推荐
- Android Studio SharedPreferences
Android 中最简单的数据存储方式 : SharedPreferences SharedPreferences 数据存储处理实际上时对一个个key——value 数据对的处理 使用SharedPr ...
- K最邻近算法(下)
import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import make_blobs from skle ...
- 干货分享:想要写好Proposal,这四个问题必须解决
当大家确定了毕业论文选题之后,下一步就是着手写开题报告,也就是proposal.开题报告或者说是研究计划要回答四个问题:为什么这个问题重要,为什么这个问题很难解决,为什么现在要考虑解决这个问题,为什么 ...
- idea新建maven web项目
一.新建maven web项目 二.配置服务器 三.测试运行
- Codeforces 392 B Blown Garland
题意:输入是由连续的RYGB和字符!组成的字符串,R代表红灯,Y代表黄灯,G代表绿灯,B代表蓝灯.简而言之,就是给定的字符串保证了下标对4取余相同的灯颜色都相同,但是有的地方为‘!’代表这个灯坏了,然 ...
- js 琐碎
1.setTimeout() .setInterval() setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式.(即n毫秒后执行一次) setTimeout(code,n) set ...
- POJ 3984:迷宫问题 bfs+递归输出路径
迷宫问题 Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11844 Accepted: 7094 Description ...
- windows driver 创建线程
VOID ThreadStart(_In_ PVOID StartContext) { PWCHAR str = (PWCHAR)StartContext; MySleep(10);//延时10ms ...
- 22 ~ express ~ 内容评论实现
1,使用 ajax 提交评论内容 给 api.js 2,数据库 contents 增加评论字段 3,后台路由 api.js 接收并完成存储 /** 增加评论(用户,内容,时间) */ router.p ...
- 数据库之存储过程Procedure
数据库之存储过程 一.概述 SQLserver中视图通过简单的select查询来解决复杂的查询,但是视图不能提供业务逻辑功能,而存储过程可以办到. 二.什么是存储过程 存储过程procedure是一组 ...