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,i−1]
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[top−1],正因为满足了 h s t [ t o p ] > h s t [ t o p − 1 ] h_{st[top]}>h_{st[top-1]} hst[top]>hst[top−1],原本 j ∈ [ s t [ t o p − 1 ] , i − 1 ] j\\in [st[top-1],i-1] j∈[st[top−1],i−1] 的区间 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[top−1]+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[top−1],i−1] 的区间 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,i−1] 中的最大值了
每个点都会入栈一次,至多出栈一次,线段树每次操作是 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+单调栈)的主要内容,如果未能解决你的问题,请参考以下文章