懒得朝硬盘的分类里放,存这了 RMQ; const int sup = 50010; int dp[sup], s[sup], x[sup], y[sup]; struct node { int mmax, mmin;//分别记录所求区间最大最小值 }pz; int n; int big[sup][35], lit[sup][35];//2^31就是int的最大范围了,big[i][j]表示的是i到i+2^j-1范围内的最大值,所以int范围内j最大到32足够 int ary[sup]; inline int Max(int a, int b) { if(a > b) return a; return b; } void Update(int w)//更新w - > n区间的最大值 { big[w][0] = dp[w]; for(int i = 1; w + (1 << i) - 1 <= n; ++ i) big[w][i] = Max(big[w][i - 1], big[w + (1 << (i - 1)) ][i - 1]); } //区间最大值,正在为看不懂线段树发愁,LX一位牛爆料ST, //给不懂线段树的菜带来了福音 inline int RMQ(int st,int ed) { if(st > ed) return 0; if(ed > n) ed = n; int k = (int) (log((double)ed - st + 1) / log(2.0)); if(k < 0) return 0; return Max( big[st][k], big[ed - (1 << k) + 1][k] ); } int main() { while(~scanf("%d", &n)) { memset(big, 0, sizeof(big)); for(int i = 1; i <= n; ++ i) scanf("%d %d %d", s + i, x + i, y + i); for(int i = n; i > 0; -- i) { dp[i] = s[i] + RMQ(i + x[i], i + y[i] - 1); Update(i); } printf("%d/n", dp[1]); } return 0; } 裸搞: const int sup = 50010; int dp[sup]; int s[sup], x[sup], y[sup]; int n; inline void MAX(int &a, int b) { if(a < b) a = b; } inline int Max(int i)//暴力枚举最优解 { int res = -1; for(int j = i + x[i]; j < i + y[i] && j <= n; ++ j) MAX(res, dp[j]); return res; } /*这个前面的决策可以影响后面的,所以dp的时候倒着推*/ //假设第i天要钱,那么最大收益就是来自未来的合法要钱天数内的某一天再次要钱,dp枚举这一天 //第i天所要钱币获得的最大收入:dp[i] = s[i] + max(dp[j + i], x[i] <= j < y[i]) int main() { while(~scanf("%d", &n)) { for(int i = 1; i <= n; ++ i) scanf("%d %d %d", s + i, x + i, y + i); for(int i = n; i > 0; -- i) dp[i] = s[i] + Max(i);//暴力枚举 printf("%d/n", dp[1] + 1); } return 0; }