题解:AT_abc417_d Takahashi's Expectation
观察到
由于
观察到题目给出
可以通过简单的二分加前缀和快速求出不断减
定义 dp 数组
dp 的初始条件为:
然后上面的问题就只需要
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M = 1e3 + 5;
const int N = 1e4 + 5;
int n, Q, p[N], a[N], b[N], to[N][M], s[N];
// to 数组即是上文提到的 F 数组,s 数组是 b 的前缀和
int main(){
ios :: sync_with_stdio(false);
cin >> n;
for(int i = 1; i <= n; i++)
cin >> p[i] >> a[i] >> b[i], s[i] = s[i - 1] + b[i];
for(int i = 0; i <= 1000; i++){
if(i <= p[n]) to[n][i] = i + a[n];
else to[n][i] = max(0, i - b[n]);
}
// dp 数组的第二维需要到 1000 而不是 500
// 因为可能会有类似 P_i = A_i = T = 500 的情况,此时 T 就会变成 1000
for(int i = n - 1; i >= 1; i--){
for(int j = 0; j <= 1000; j++){
if(j <= p[i]) to[i][j] = to[i + 1][j + a[i]];
else to[i][j] = to[i + 1][max(0, j - b[i])];
}
}
cin >> Q;
int x;
while(Q--){
cin >> x;
int l = 1, r = n, mid, ans = -1;
// ans 记录什么时候 T 第一次减至 500 及以下
while(l <= r){
mid = ((r - l) >> 1) + l;
if(x - s[mid] <= 500) ans = mid, r = mid - 1;
else l = mid + 1;
}
if(ans == -1){
// ans == -1 表示减到最后 T 仍然大于 500
cout << x - s[n] << "\n";
continue;
}
x = max(0, x - s[ans - 1]);
cout << to[ans][x] << "\n";
}
return 0;
}