题解:AT_abc417_d [ABC417D] Takahashi's Expectation
Exscallop64_ · · 题解
题目简述
给定一个正整数
- 若
p_i \ge x ,则x 变为x + a_i ;否则,x 变为\max(x - b_i,0) 。
对于每个询问输出最终的
思路
我们不难想到 DP,令
-
若
p_{i + 1} \ge j ,则dp_{i,j} = dp_{i+1,j+a_{i+1}} 。 -
若
p_{i+1} < j ,则dp_{i,j} = dp_{i+1,\max(0,j-b_{i+1})} 。
每次查询
以下我们令
可以发现,如果
那么我们再来思考
我们只用对
复杂度分析
-
时间复杂度:
O(n(\max_{i=1}^{n} p_i+a_i) + q \log n) 。(为什么带个\log ,因为需要二分查找) -
空间复杂度:
O(n(\max_{i=1}^{n} p_i+a_i)) 。
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
const int MAXN = 1e4 + 5, MAXV = 1e3 + 1;
//这里我索性将上限提为 1000
int n, q, p[MAXN], a[MAXN], b[MAXN], dp[MAXN][MAXV], sum[MAXN];
int Calc(int x){
if(x < MAXV) return dp[0][x];
int pos = lower_bound(sum + 1, sum + 1 + n, x - MAXV + 1) - sum;//二分找到临界点
return pos <= n ? dp[pos][max(0, x - sum[pos])] : x - sum[n];
}
int main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n;
for(int i = 1; i <= n; i++){
cin >> p[i] >> a[i] >> b[i];
sum[i] = sum[i - 1] + b[i];//b 的前缀和
}
for(int i = 0; i < MAXV; i++) dp[n][i] = i;//初始化
for(int i = n - 1; i >= 0; i--){//DP
for(int j = 0; j < MAXV; j++){
dp[i][j] = p[i + 1] >= j ? dp[i + 1][j + a[i + 1]] : dp[i + 1][max(0, j - b[i + 1])];
}
}
cin >> q;
for(int x; q; q--){
cin >> x;
cout << Calc(x) << '\n';
}
return 0;
}