• 2019牛客暑期多校训练营(第一场)I dp+线段树


    题意

    给出n个点,每个点有a,b两个属性,让你从左下角到右上角划一条线,线的左边每个点的贡献是(a_i),线的右边每个点的贡献是(b_i),使得两部分的总和最大。

    分析

    在这里插入图片描述

    找一条折线将点分割开,使总和最大。

    把y离散化,然后点按x排序,设(dp[i])为经过第(i)个点(该点当作B集合中的点)的折线的权值,之前的点中在这个点上面的点dp值要加上(b[i]),之前的点中在这个点下面的点的dp值要加上(a[i])

    • (dp[i]=max(dp[i],dp[k]+b[i]),y[k]<=y[i])
    • (dp[k]=dp[k]+b[i],y[k]>y[i])
    • (dp[k]=dp[k]+a[i],y[k]<y[i])

    用线段树来维护dp值就行了

    Code

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,mid,p<<1
    #define rson mid+1,r,p<<1|1
    #define ll long long
    using namespace std;
    const int inf=1e9;
    const int mod=1e9+7;
    const int maxn=1e5+10;
    int n;
    struct ppo{
    	int x,y,a,b;
    	bool operator <(const ppo &r) const{
    		if(x==r.x) return y>r.y;
    		return x<r.x;
    	}
    }a[maxn];
    int b[maxn],m;
    ll tr[maxn<<2],tag[maxn<<2];
    void pp(int p){
    	tr[p]=max(tr[p<<1],tr[p<<1|1]);
    }
    void pd(int p,ll k){
    	tr[p]+=k;tag[p]+=k;
    }
    void bd(int l,int r,int p){
    	tag[p]=0;
    	if(l==r){
    		tr[p]=0;return;
    	}int mid=l+r>>1;
    	bd(lson);bd(rson);pp(p);
    }
    void up(int x,int l,int r,int p,ll k){
    	if(l==r){
    		tr[p]=max(tr[p],k);return;
    	}int mid=l+r>>1;
    	pd(p<<1,tag[p]);pd(p<<1|1,tag[p]);tag[p]=0;
    	if(x<=mid) up(x,lson,k);
    	else up(x,rson,k);pp(p);
    }
    void add(int dl,int dr,int l,int r,int p,ll k){
    	if(l>r) return;
    	if(l>=dl&&r<=dr){
    		tr[p]+=k;tag[p]+=k;return;
    	}int mid=l+r>>1;
    	pd(p<<1,tag[p]);pd(p<<1|1,tag[p]);tag[p]=0;
    	if(dl<=mid) add(dl,dr,lson,k);
    	if(dr>mid) add(dl,dr,rson,k);pp(p);
    }
    ll qy(int dl,int dr,int l,int r,int p){
    	if(l>r) return 0;
    	if(l>=dl&&r<=dr){
    		return tr[p];
    	}int mid=l+r>>1;ll ret=0;
    	pd(p<<1,tag[p]);pd(p<<1|1,tag[p]);tag[p]=0;
    	if(dl<=mid) ret=max(ret,qy(dl,dr,lson));
    	if(dr>mid) ret=max(ret,qy(dl,dr,rson));
    	return ret;
    }
    int main(){
    	//ios::sync_with_stdio(false);
    	//freopen("in","r",stdin);
    	while(~scanf("%d",&n)){
    		for(int i=1;i<=n;i++){
    			scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].a,&a[i].b);
    			b[i]=a[i].y;
    		}
    		sort(b+1,b+n+1);
    		m=unique(b+1,b+n+1)-b-1;
    		for(int i=1;i<=n;i++){
    			a[i].y=lower_bound(b+1,b+m+1,a[i].y)-b+1;
    		}
    		sort(a+1,a+n+1);
    		m++;
    		bd(1,m,1);
    		for(int i=1;i<=n;i++){
    			ll ret=qy(1,a[i].y,1,m,1);
    			up(a[i].y,1,m,1,ret+a[i].b);
    			add(1,a[i].y-1,1,m,1,a[i].a);
    			add(a[i].y+1,m,1,m,1,a[i].b);
    		}
    		printf("%lld
    ",tr[1]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Spring框架中的单例Beans是线程安全的么?
    四种类型的数据节点 Znode?
    什么是 Swagger?你用 Spring Boot 实现了它吗?
    服务注册和发现是什么意思?Spring Cloud 如何实现?
    如何使用 Spring Boot 实现异常处理?
    什么是 CSRF 攻击?
    什么是 WebSockets?
    springboot整合Hbase
    java8的Supplier
    @Scope注解的作用详解
  • 原文地址:https://www.cnblogs.com/xyq0220/p/11386007.html
Copyright © 2020-2023  润新知