题解:AT_abc417_d [ABC417D] Takahashi Expectation

DerRichter Lv2

题意

给定 个三元组 ,定义心情值为 ,需要按照 的顺序执行以下操作:

  • ,那么
  • 否则

给定 次查询,每次查询给定一个整数 ,要求求出初始心情值为 时,最终的心情值。

思路

本场总结:E < D。

我们发现,如果 ,那么一定会减少到 以下,且如果数据开满,那么心情值会在 以内上下乱跳。而 ,所以我们可以预处理出 以内的从 开始操作的答案。

接着考虑非常大的数如何转化为小数。我们发现,操作时,减少到 以内的操作是一段前缀。而停止的条件是 ,也就是 。而 的最大值是 。对于不同的数据,我们设这个最大值为 ,且对于一个 的数 ,记其转化为小数后的结果为 ,且停止减少的第一轮操作是第 轮。

转化为小数后,并不能直接按照从 开始的答案计算。因为前面已经跳过了一些步骤,所以我们还需要处理出从给定的操作步骤开始的答案。

所以,我们将答案分为三段处理:

  • ,直接求解;
  • ,那么给 挂上查询 ,其中 表示当前的查询下标。
  • ,那么最后也无法减少到 以内,直接输出 即可。

但是,注意一点,如果我们直接处理出 以内每个数从每一轮开始的答案,实际上是会超时的。因为此题答案不能反推,所以需要 的时间来预处理,会超时。

所以,如前面 部分所言,我们将操作离线,分为两个函数:

  • 第一个用来处理 数组的值。
  • 第二个用来离线处理查询。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <bits/stdc++.h>

using namespace std;
using ll = long long;
using pii = pair<int, int>;

const int MAXN = 1e4 + 10, MAXV = 1e3 + 10, MAXQ = 5e5 + 10;

struct Query {
int i, id;
};

struct Node {
int p, a, b;
} a[MAXN];

int n, q, mx, sum;
int res[MAXV], ans[MAXQ];
pii val[MAXN * MAXV];
vector<Query> v[MAXN];
vector<int> r;

void change(int &k, int i) {
k <= a[i].p ? k += a[i].a : k = max(0, k - a[i].b);
}

void init() { // 预处理
// 时间复杂度 O(NV)
for (int i = 1; i <= n; i++) {
sum += a[i].b;
for (int j = mx + 1; j <= sum + a[i].p; j++) {
val[j] = {j - (sum - a[i].b), i};
}
mx = max(mx, sum + a[i].p);
}
}

void solve() { // 求解答案
// 时间复杂度 O(NV)
for (int i = 0; i <= 1000; i++) {
int k = i;
for (int j = 1; j <= n; j++) {
change(k, j);
}
res[i] = k;
for (Query &x : v[i]) {
int k = i;
for (int j = x.i; j <= n; j++) {
change(k, j);
}
ans[x.id] = k;
}
}
}

int main() {
ios::sync_with_stdio(0), cin.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i].p >> a[i].a >> a[i].b;
}
init();
cin >> q;
r.assign(q + 5, 0);
for (int i = 1; i <= q; i++) {
cin >> r[i];
// 将可以求解的大数据挂到小数据上做查询
if (r[i] > 1000 && r[i] <= mx) {
v[val[r[i]].first].push_back({val[r[i]].second, i});
}
}
solve();
// 离线查询
for (int i = 1; i <= q; i++) {
if (r[i] <= 1000) {
ans[i] = res[r[i]];
} else if (r[i] > mx) {
ans[i] = r[i] - sum;
}
cout << ans[i] << '\n';
}
return 0;
}
  • 标题: 题解:AT_abc417_d [ABC417D] Takahashi Expectation
  • 作者: DerRichter
  • 创建于 : 2026-08-15 00:08:08
  • 更新于 : 2026-08-15 07:16:04
  • 链接: https://derrichter.onrender.com/2026/08/15/题解:AT-abc417-d-ABC417D-Takahashi-Expectation/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论
目录
题解:AT_abc417_d [ABC417D] Takahashi Expectation