CF1482E Skyline Photo

Description

Alice is visiting New York City. To make the trip fun, Alice will take photos of the city skyline and give the set of photos as a present to Bob. However, she wants to find the set of photos with maximum beauty and she needs your help.

There are $n$ buildings in the city, the $i$-th of them has positive height $h_i$. All $n$ building heights in the city are different. In addition, each building has a beauty value $b_i$. Note that beauty can be positive or negative, as there are ugly buildings in the city too.

A set of photos consists of one or more photos of the buildings in the skyline. Each photo includes one or more buildings in the skyline that form a contiguous segment of indices. Each building needs to be in exactly one photo. This means that if a building does not appear in any photo, or if a building appears in more than one photo, the set of pictures is not valid.

The beauty of a photo is equivalent to the beauty $b_i$ of the shortest building in it. The total beauty of a set of photos is the sum of the beauty of all photos in it. Help Alice to find the maximum beauty a valid set of photos can have.

Solution

设$dp_i$表示考虑前$i$个建筑的答案,求出$i$前面的第一个高度比$h_i$小的位置$j$,可以用单调队列求出

如果$j$与$i$在同一张照片,此时的答案就是$dp_j$

如果$j$与$i$不在同一张照片,因为$i$是$(j,i]$中最低的,所以此时的答案就是$dp_k+b_i$,其中$j leq k < i$,可以用线段树求出

时间复杂度$O(n log n)$

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int n,h[300005],b[300005],sta[300005],top,L[300005];
long long dp[300005],val[1200005];
const long long inf=0x7f7f7f7f7f7f7f7f;
inline int read(){
    int f=1,w=0;
    char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=getchar();
    return f*w;
}
void build(int i,int l,int r){
    val[i]=-inf;
    if(l==r)return;
    int mid=l+r>>1;
    build(i<<1,l,mid),build(i<<1|1,mid+1,r);
}
long long query(int i,int l,int r,int L,int R){
    if(L<=l&&r<=R)return val[i];
    int mid=l+r>>1;
    long long ret=-inf;
    if(L<=mid)ret=max(ret,query(i<<1,l,mid,L,R));
    if(R>mid)ret=max(ret,query(i<<1|1,mid+1,r,L,R));
    return ret;
}
void update(int i,int l,int r,int p,long long v){
    if(l==r){val[i]=max(val[i],v);return;}
    int mid=l+r>>1;
    if(p<=mid)update(i<<1,l,mid,p,v);
    else update(i<<1|1,mid+1,r,p,v);
    val[i]=max(val[i<<1],val[i<<1|1]);
}
int main(){
    n=read();
    for(int i=1;i<=n;i++)h[i]=read();
    for(int i=1;i<=n;i++)b[i]=read();
    build(1,0,n),dp[0]=-inf,update(1,0,n,0,0);
    for(int i=1;i<=n;i++){
        while(top&&h[sta[top]]>=h[i])--top;
        L[i]=sta[top],sta[++top]=i,dp[i]=max(query(1,0,n,L[i],i-1)+b[i],dp[L[i]]),update(1,0,n,i,dp[i]);
    }
    printf("%lld
",dp[n]);
    return 0;
}
Skyline Photo
原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/14582382.html