CodeForces - 1484E Skyline Photo(dp+单调栈)

Posted Frozen_Guardian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeForces - 1484E Skyline Photo(dp+单调栈)相关的知识,希望对你有一定的参考价值。

题目链接:点击查看

题目大意:给出 n n n 个建筑,每个建筑有一个高度和一个美丽值,现在要求划分为数个连续的区间,使得所有区间的贡献之和最大,其中每个区间的贡献值为,区间中高度最低的建筑物的美丽值

题目分析:不难分析出一个很简单的经典区间划分 d p dp dp,时间复杂度是 O ( n 2 ) O(n^2) O(n2) 的:

d p i = m a x ( d p j + v a l ( j + 1 , i ) ) dp_i=max(dp_j+val(j+1,i)) dpi=max(dpj+val(j+1,i)),其中 j ∈ [ 0 , i − 1 ] j\\in[0,i-1] j[0,i1]

v a l ( l , r ) val(l,r) val(l,r) 代表的是 [ l , r ] [l,r] [l,r] 作为一段区间的贡献,也就是高度最小值位置的美丽值

一开始感觉是直接将 d p + v a l dp+val dp+val 扔进线段树然后每次 l o g ( n ) log(n) log(n) 转移,但是卡在了插入一个新点后更新前面所有 v a l val val 的操作,看了题解后发现是可以直接在单调栈弹栈的时候维护答案,感觉这个模型确实蛮经典的样子

就比如用单调栈维护一个单调递增的序列,在需要插入第 i i i 个点的时候,因为需要维护单调栈,所以大于 h i h_i hi 的点都需要被弹掉

考虑被弹出去的点 s t [ t o p ] st[top] st[top] 和栈顶前面的一个点 s t [ t o p − 1 ] st[top-1] st[top1],正因为满足了 h s t [ t o p ] > h s t [ t o p − 1 ] h_{st[top]}>h_{st[top-1]} hst[top]>hst[top1],原本 j ∈ [ s t [ t o p − 1 ] , i − 1 ] j\\in [st[top-1],i-1] j[st[top1],i1] 的区间 v a l ( j + 1 , i ) val(j+1,i) val(j+1,i) 的值为 a s t [ t o p ] a_{st[top]} ast[top]。因为大于 h s t [ t o p ] h_{st[top]} hst[top] 的点都已经被 s t [ t o p ] st[top] st[top] 弹出去了,所以到目前为止 h s t [ t o p ] h_{st[top]} hst[top] 一定是区间 [ s t [ t o p − 1 ] + 1 , i ] [st[top-1]+1,i] [st[top1]+1,i] 这段区间中的最小值了

继续上述的论证,当 s t [ t o p ] st[top] st[top] 被弹出去后,点 i i i 一定是需要进栈的,就目前而言,此时 j ∈ [ s t [ t o p − 1 ] , i − 1 ] j\\in [st[top-1],i-1] j[st[top1],i1] 的区间 v a l ( j + 1 , i ) val(j+1,i) val(j+1,i) h s t [ t o p ] h_{st[top]} hst[top] 变成了 h i h_i hi

上面两段就是在插入点 i i i 时更新线段树的操作,最后答案显然就是区间询问 [ 0 , i − 1 ] [0,i-1] [0,i1] 中的最大值了

每个点都会入栈一次,至多出栈一次,线段树每次操作是 l o g ( n ) log(n) log(n) 的,所以时间复杂度是 O ( n l o g n ) O(nlogn) O(nlogn)

代码:

// Problem: E. Skyline Photo
// Contest: Codeforces - Codeforces Round #709 (Div. 2, based on Technocup 2021 Final Round)
// URL: https://codeforces.com/contest/1484/problem/E
// Memory Limit: 256 MB
// Time Limit: 2500 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// #pragma GCC optimize(2)
// #pragma GCC optimize("Ofast","inline","-ffast-math")
// #pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#include<list>
#include<unordered_map>
#define lowbit(x) x&-x
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
template<typename T>
inline void read(T &x)
{
	T f=1;x=0;
	char ch=getchar();
	while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	x*=f;
}
template<typename T>
inline void write(T x)
{
	if(x<0){x=~(x-1);putchar('-');}
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
const LL inf=0x3f3f3f3f3f3f3f3f;
const int N=1e6+100;
int h[N],a[N];
LL dp[N];
struct Node {
	int l,r;
	LL mmax,lazy;
}tree[N<<2];
void pushup(int k) {
	tree[k].mmax=max(tree[k<<1].mmax,tree[k<<1|1].mmax);
}
void pushdown(int k) {
	if(tree[k].lazy) {
		LL lz=tree[k].lazy;
		tree[k].lazy=0;
		tree[k<<1].mmax+=lz;
		tree[k<<1|1].mmax+=lz;
		tree[k<<1].lazy+=lz;
		tree[k<<1|1].lazy+=lz;
	}
}
void build(int k,int l,int r) {
	tree[k]={l,r,-inf,0};
	if(l==r) {
		return;
	}
	int mid=(l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
}
void update(int k,int pos,LL val) {
	if(tree[k].l==tree[k].r) {
		tree[k].mmax=val;
		return;
	}
	pushdown(k);
	int mid=(tree[k].l+tree[k].r)>>1;
	if(pos<=mid) {
		update(k<<1,pos,val);
	} else {
		update(k<<1|1,pos,val);
	}
	pushup(k);
}
void update(int k,int l,int r,LL val) {
	if(tree[k].l>r||tree[k].r<l) {
		return;
	}
	if(tree[k].l>=l&&tree[k].r<=r) {
		tree[k].mmax+=val;
		tree[k].lazy+=val;
		return;
	}
	pushdown(k);
	update(k<<1,l,r,val);
	update(k<<1|1,l,r,val);
	pushup(k);
}
LL query(int k,int l,int r) {
	if(tree[k].l>r||tree[k].r<l) {
		return -inf;
	}
	if(tree[k].l>=l&&tree[k].r<=r) {
		return tree[k].mmax;
	}
	pushdown(k);
	return max(query(k<<1,l,r),query(k<<1|1,l,r));
}
int main()
{
#以上是关于CodeForces - 1484E Skyline Photo(dp+单调栈)的主要内容,如果未能解决你的问题,请参考以下文章

如何看codeforces做了多少题

codeforces上怎么看测试数据

codeforces比赛后怎么看题解和答案

codeforces是啥?

codeforces Codeforces 650A Watchmen

CodeForces - 504A && CodeForces - 624C && CodeForces - 2B