线段树优化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全部投资的获利。 #includestdio.h#includestring.h#includestdlib.htypedef long long ll;int
线段树优化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]);
}
}