FZU 2079 最大获利

线段树优化DP

是dp[i]=max{dp[j]+w[j+1][i],dp[i-1]},其中1=<i<=n,0=<j<=j-1;

dp[i]表示前i个项目的最大获利,w[j][i]表示项目j到i全部投资的获利。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef long long ll;
int n,m;
int a[20010];
struct Item{
	int l,r;
	ll v;
}item[20010];
ll dp[20010],w[70010],p[70010];                     //用数组p[]标记需要向下压多少,数组w[]存最大值
int cmp(const void * a,const void * b){
	struct Item * aa=(struct Item * )a;
	struct Item * bb=(struct Item * )b;
	return aa->r-bb->r;
}
int max(int a,int b){
	return a>b?a:b;
}
void insert(int c,int l,int r,int a,int b,ll val){
	int mid;
	if(a==l && b==r){
		w[c]+=val;
		p[c]+=val;
		return;
	}
	if(p[c]!=0){
		w[2*c+1]+=p[c];
		p[2*c+1]+=p[c];
		w[2*c]+=p[c];
		p[2*c]+=p[c];
		p[c]=0;
	}
	mid=(l+r)>>1;
	if(a>mid)
		insert(c*2+1,mid+1,r,a,b,val);
	else if(b<=mid)
		insert(c*2,l,mid,a,b,val);
	else{
		insert(c*2,l,mid,a,mid,val);
		insert(c*2+1,mid+1,r,mid+1,b,val);
	}
	w[c]=max(w[2*c+1],w[2*c]);
}
ll query(int c,int l,int r,int a,int b){
	int mid;
	if(a==l && b==r)
		return w[c];
	if(p[c]!=0){
		w[2*c+1]+=p[c];
		p[2*c+1]+=p[c];
		w[2*c]+=p[c];
		p[2*c]+=p[c];
		p[c]=0;
	}
	mid=(l+r)>>1;
	if(a>mid)
		return query(c*2+1,mid+1,r,a,b);
	else if(b<=mid)
		return query(c*2,l,mid,a,b);
	else
		return max(query(c*2,l,mid,a,mid),query(c*2+1,mid+1,r,mid+1,b));
	w[c]=max(w[2*c+1],w[2*c]);
}
int main(){
	int i,j;
	while(scanf("%d %d",&n,&m)==2){
		for(i=1;i<=n;i++)
			scanf("%d",&a[i]);
		for(i=1;i<=m;i++)
			scanf("%d %d %lld",&item[i].l,&item[i].r,&item[i].v);
		qsort(&item[1],m,sizeof(item[1]),cmp);
		i=1;j=1;
		memset(dp,0,sizeof(dp));
		memset(w,0,sizeof(w));
		memset(p,0,sizeof(p));
		for(;i<=n;i++){
			insert(1,0,n,0,i-1,-a[i]);
			while(j<=m && item[j].r<=i){
				insert(1,0,n,0,item[j].l-1,item[j].v);
				j++;
			}
			dp[i]=max(dp[i-1],query(1,0,n,0,i-1));            //dp[i]表示前i个项目的最大获利
			insert(1,0,n,i,i,dp[i]);
		}
		printf("%lld\n",dp[n]);
	}
}


 

你可能感兴趣的:(FZU 2079 最大获利)