专栏文章
题解:AT_abc417_d [ABC417D] Takahashi's Expectation
AT_abc417_d题解参与者 4已保存评论 3
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 3 条
- 当前快照
- 1 份
- 快照标识符
- @miojzwxp
- 此快照首次捕获于
- 2025/12/02 20:27 3 个月前
- 此快照最后确认于
- 2025/12/02 20:27 3 个月前
题目简述
给定一个正整数 ,及 个长度为 的数组 、、, 次询问,每次给定一个 ,对于每个 ,依次执行以下操作:
- 若 ,则 变为 ;否则, 变为 。
对于每个询问输出最终的 。
思路
我们不难想到 DP,令 为执行完 ,当前数为 ,若执行完 后的答案。那么显然我们有如下转移。
-
若 ,则 。
-
若 ,则 。
每次查询 ,则答案为 。不过注意到 最大有 ,显然不可行。
以下我们令 。
可以发现,如果 那么一定是有一段 的前缀,在此前缀中一定是一直减 ,直到 才有可能不会再减,这样我们可以把 的问题转换为 的问题。(找到这个临界点可以使用二分)
那么我们再来思考 ,可以观察到 在依次执行操作期间上限至多 ,显然在执行完 后要在第 次增加, 至多 ,所以执行完 后至多 ,所以总上限为 。
我们只用对 范围内的 DP 即可。
复杂度分析
-
时间复杂度:。(为什么带个 ,因为需要二分查找)
-
空间复杂度:。
#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;
}
相关推荐
评论
共 3 条评论,欢迎与作者交流。
正在加载评论...