Codeforces Round #709 (Div. 2, based on Technocup 2021 Final Round) E. Skyline Photo

题意

给定n个建筑,每个建筑的高度为hi(hi唯一),每个建筑有一个美丽值为bi,给这些建筑拍照,拍照的要求是每次拍照的建筑必须是连续的,每个建筑只能且精确的出现在一张照片,每个照片的美丽值为这个照片里面的最低建筑物的美丽值。
求所有照片的美丽值之和最大。
n<=3e5 -1e9 <= bi <= 1e9

思路

以第i张建筑为结尾拍照,可以分为考虑第i张照片的美丽值和不考虑两种情况,考虑的话又有两种情况,1.自己一张照片 2.和前面连续的都比它高的在一张照片,不考虑是从前面比它小的在一张照片

定义f[i]表示以第i个建筑结尾拍照的最大美丽值
用转移方程表示为
1.f[i] = f[i - 1] + b[i]
2.f[i] = max(f[k] ) + b[i] 表示第i个建筑之前到第一个比它低的建筑物之间的最大美丽值加上第i个建筑的美丽值(只需要保证h[k] 最小)应该包含k,但是我第一次没有包含k竟然也过了,因为第k个代表所有大的都在这里面。
3.f[i] = f[k] k表示i之前第一个比它低的建筑下标(可以通过传递性,因为在第k张照片的时候考虑了比它小的)
在只用找第一个比他小的,可以使用单调栈
但是这并不能表示第二情况求max(f[k]),根据单调栈的性质我们可以把比它大的都会删除,只用考虑max(f[k])我们可以把这个信息保留在这个点上,用一个栈来维护。

代码

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<unordered_set>
#include<unordered_map>

using namespace std;
#define x first
#define y second
#define int long long
typedef pair<int ,int > PII;
typedef long long ll;
const int N = 3e5 + 10;
int h[N];
int b[N]; 
int f[N];
int q[N];
int maxp[N];
signed main(){
	int n;
	scanf("%lld",&n);
	for(int i = 1;i <= n;i++){
		scanf("%lld",&h[i]);
	}
	for(int i = 1;i <= n;i++){
		scanf("%lld",&b[i]);
	}
	int tt = 0;
	h[0] = 2e9;
	maxp[0] = 0;
	for(int i = 1;i <= n;i++){
		f[i] = f[i - 1] + b[i];
		int mp = -2e9;
		while(0 <= tt && h[q[tt]] >= h[i]) mp = max(mp,maxp[tt --]);
		f[i] = max(mp + b[i],f[i]);
		if(q[tt] != 0 ) f[i] = max(max(f[q[tt]],f[q[tt]] + b[i]),f[i]);
		q[++tt] = i;
		maxp[tt] = max(mp,f[i]);
	}
	cout << f[n] ;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值