zoukankan      html  css  js  c++  java
  • CF709 C. Skyline Photo(线段树优化DP)

    CF709 C. Skyline Photo(线段树优化DP)

    传送门

    题意:给两个数组,分别表示分数和高度,你可以将数组分成若干段,每段贡献为其高度最低的分数,求最高分数和。

    题解:

    好题,首先先考虑n*n做法,f[i]表示将前i段分成若干段的最大值,则f[n]即表示答案,易得递推方程:f[i]=max(f[i], f[j]+区间最低高度的分数)

    所以我们便可以用线段树优化,处理区间最低高度的分数与f[j]的最大值。

    然后每次循环开始时,第i个高度,会使一段区间的最低高度改变,二分线段树找到最远影响位置,同时区间修改影响的高度与分数,易知分f的值不会改变,所以只需储存区间内f的最大值,在区间修改完分数后,区间最大值就是分数+f的最大值。

    #include<iostream>
    using namespace std;
    #define ll long long
    const ll N=3e5+7;
    const ll inf=1e9;
    ll n,b[N],a[N];
    struct madoka{
    	ll l;
    	ll r;
    	ll f;
    	ll b;
    	ll dp;
    	ll sum;
    }ma[N*4];
    void build(ll l,ll r,ll k){
    	ma[k].l=l;
    	ma[k].r=r;
    	if(l==r){
    		ma[k].b=inf;
    		return;
    	}
    	ll mid=(l+r)/2;
    	build(l,mid,k*2);
    	build(mid+1,r,k*2+1);
    	ma[k].b=max(ma[k*2].b,ma[k*2+1].b);
    }
    void down(ll k){
    	if(ma[k].f&&ma[k].l!=ma[k].r){
    		ma[k*2].f=ma[k].f;
    		ma[k*2].b=b[ma[k].f];
    		ma[k*2].sum=ma[k*2].dp+a[ma[k].f];
    		ma[k*2+1].f=ma[k].f;
    		ma[k*2+1].b=b[ma[k].f];
    		ma[k*2+1].sum=ma[k*2+1].dp+a[ma[k].f];
    		ma[k].f=0;
    	}
    }
    ll fin(ll k,ll h){
    	down(k);
    	if(ma[k].l==ma[k].r){
    		return ma[k].l;
    	}
    	ll mid=(ma[k].l+ma[k].r)/2;
    	if(ma[k*2].b>=h){
    		return fin(k*2,h);
    	}
    	else{
    		return fin(k*2+1,h);
    	}
    }
    void up(ll k,ll l,ll r){
    	down(k);
    	if(l<=ma[k].l&&ma[k].r<=r){
    		ma[k].b=b[r];
    		ma[k].sum=a[r]+ma[k].dp;
    		ma[k].f=r;
    		return;
    	}
    	ll mid=(ma[k].l+ma[k].r)/2;
    	if(l<=mid){
    		up(k*2,l,r);
    	}
    	if(mid<r){
    		up(k*2+1,l,r);
    	}
    	ma[k].dp=max(ma[k*2].dp,ma[k*2+1].dp);
    	ma[k].sum=max(ma[k*2].sum,ma[k*2+1].sum);
    	ma[k].b=max(ma[k*2].b,ma[k*2+1].b);
    }
    void up_dp(ll k,ll p,ll z){
    	down(k);
    	if(ma[k].l==ma[k].r){
    		ma[k].dp=z;
    		return;
    	}
    	ll mid=(ma[k].l+ma[k].r)/2;
    	if(p<=mid){
    		up_dp(k*2,p,z);
    	}
    	else{
    		up_dp(k*2+1,p,z);
    	}
    	ma[k].dp=max(ma[k*2].dp,ma[k*2+1].dp);
    	ma[k].sum=max(ma[k*2].sum,ma[k*2+1].sum);
    	ma[k].b=max(ma[k*2].b,ma[k*2+1].b);
    }
    ll qry(ll k,ll l,ll r){
    	down(k);
    	if(l<=ma[k].l&&ma[k].r<=r){
    		return ma[k].sum;
    	}
    	ll mid=(ma[k].l+ma[k].r)/2;
    	ll res=-inf;
    	if(l<=mid){
    		res=max(res,qry(k*2,l,r));
    	}
    	if(mid<r){
    		res=max(res,qry(k*2+1,l,r));
    	}
    	return res;
    }
    int main(){
    	scanf("%lld",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%lld",&b[i]);
    	}
    	for(int i=1;i<=n;i++){
    		scanf("%lld",&a[i]);
    	}
    	build(1,n,1);
    	for(int i=1;i<=n;i++){
    		ll p=fin(1,b[i]);
    		up(1,p,i);
    		ll mx=qry(1,1,i);
    		up_dp(1,i+1,mx);
    		if(i==n){
    			printf("%lld
    ",mx);
    		}
    	}
    }
    
  • 相关阅读:
    图解Python 【第八篇】:网络编程-进程、线程和协程
    TCP协议三次握手、四次挥手过程
    OSI七层模型与TCP/IP五层模型
    TCP/IP协议分为哪四层,具体作用是什么。
    app测试中,ios和android的区别
    APP在用户设备发生crash,应该怎么修复
    Android四层架构
    安卓四大组件、六大布局、五大存储
    测试工程师准备找工作,需要准备什么?
    接口测试响应码解析
  • 原文地址:https://www.cnblogs.com/whitelily/p/14596540.html
Copyright © 2011-2022 走看看