DP+线段树,
dp[i]记录从i开始的最大收益,
dp[i]=s[i]+max(dp[x]|i+x[i]<=x<i+y[i]);
利用线段树维护个最大值就行了
#include<cstdio> #define MAXN 50010 #define max(a,b) ((a)>(b))?(a):(b) int n,s[MAXN],x[MAXN],y[MAXN]; int seg[4*MAXN]; int dp[MAXN]; void up(int x) { seg[x]=max(seg[2*x],seg[2*x+1]); } void build(int l,int r,int i) { seg[i]=0; if(l==r) return; int m=(l+r)>>1; build(l,m,2*i); build(m+1,r,2*i+1); } void ud(int l,int r,int pos,int i,int x) { if(l==r&&l==pos) { seg[i]=x; return; } int mid=(l+r)>>1; if(mid>=pos) ud(l,mid,pos,2*i,x); else ud(mid+1,r,pos,2*i+1,x); up(i); } int qu(int l,int r,int a,int b,int i) { if(l==a&&r==b) return seg[i]; int mid=(l+r)>>1; if(mid>=b) return qu(l,mid,a,b,2*i); else if(a>mid) return qu(mid+1,r,a,b,2*i+1); else return max(qu(l,mid,a,mid,2*i),qu(mid+1,r,mid+1,b,2*i+1)); } int main() { while(scanf("%d",&n)!=EOF) { build(1,n,1); for(int i=1;i<=n;i++) scanf("%d%d%d",s+i,x+i,y+i); dp[n]=s[n]; for(int i=n-1;i>=1;i--) { ud(1,n,i+1,1,dp[i+1]); if(i+y[i]-1<=n) dp[i]=s[i]+qu(1,n,i+x[i],i+y[i]-1,1); else if(i+x[i]<=n) dp[i]=s[i]+qu(1,n,i+x[i],n,1); else dp[i]=s[i]; } printf("%d\n",dp[1]); } return 0; }