0%

Educational Codeforces Round 187 (Rated for Div. 2)-CF-Edu-187-E. Probabilistic Card Game

题目大意

https://codeforces.com/contest/2203/problem/E

题目描述

Alice 和 Bob 有一个初始为空的牌堆。游戏共进行 mm 回合,在第 ii 回合中,会发生以下事件:

  1. 一张数值为 aia_i 的牌被加入牌堆(保证加入的牌数值各不相同)。

  2. 如果牌堆中的牌数少于 33 张,该回合直接结束。

  3. 否则,Alice 从牌堆中选择一张牌,设其数值为 aa

  4. 接着,Bob 在知道 Alice 选了哪张牌的情况下,从剩下的牌中选择一张牌,设其数值为 bbbab \neq a)。

  5. 最后,从剩下的 i2i-2 张牌中等概率随机抽取一张牌,设其数值为 cc

  6. 回合结束后,这三张牌被放回牌堆。

得分规则

在确定了 a,b,ca, b, c 的值后,Bob 的得分按以下规则计算:

  • 如果 acbc|a - c| \le |b - c|,Bob 得 00 分;

  • 如果 cc 的值严格介于 aabb 之间(即 a<c<ba < c < bb<c<ab < c < a),Bob 得 00 分;

  • 其他情况下,Bob 得分为 bc|b - c|

游戏目标

在每回合中,Alice 的目标是最小化 Bob 的期望得分,而 Bob 的目标是最大化他的期望得分。两人均采取最优策略。(注意:两人是根据真实期望得分来做最小化或最大化的决策,而非取模后的值)。

输入格式

第一行包含一个整数 mm3m21053 \le m \le 2 \cdot 10^5),表示回合数。
第二行包含 mm 个整数 a1,a2,,ama_1, a_2, \dots, a_m1ai10121 \le a_i \le 10^{12},所有 aia_i 互不相同),表示每回合加入牌堆的牌的数值。

输出格式

输出 m2m-2 个整数,第 ii 个数表示在第 i+2i+2 回合中,双方在最优策略下 Bob 的期望得分对 998244353998244353 取模后的结果。

样例 1

1
2
3
4
5
6
7
8
Input:
5
1 10 3 11 7

Output:
0
499122177
665496236

样例 1 解释

这三个输出分别对应第 3,4,53, 4, 5 回合。真实的期望得分依次为 0,12,230, \frac{1}{2}, \frac{2}{3}

样例 2

1
2
3
4
5
6
7
8
9
Input:
6
23 7 11 24 10 28

Output:
0
499122177
1
748683266

样例 2 解释

这四个输出分别对应第 3,4,5,63, 4, 5, 6 回合。真实的期望得分依次为 0,12,1,540, \frac{1}{2}, 1, \frac{5}{4}

样例 3

1
2
3
4
5
6
7
8
9
10
11
12
Input:
9
4 10 7 1 16 5 9 12 2

Output:
0
499122178
2
499122178
798595484
831870296
427819010

样例 3 解释

真实的期望得分依次为 0,32,2,32,85,116,1170, \frac{3}{2}, 2, \frac{3}{2}, \frac{8}{5}, \frac{11}{6}, \frac{11}{7}

思路讲解

通过模拟,我们发现,首先,选了 A 的位置以后,B 其实只有两种选择,B 必须紧紧挨着 A 选。

然后,我们就是要确定这个 A 的选择。我们可以采用一种二分两次的方法(我自己瞎想的)。或者你也可以三分。

image

图中的 res 就是使用树状数组查询的蓝色部分的这个查询结果。

核心的这个做法这个 lambda 是这个东西,他能够在知道目前长度的情况下,求解出这个答案。

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
    auto find_ans = [&](ll len) -> ll {
ll l = 0, r = len - 1;
auto cal_left = [&](ll ia) -> ll {
ll pa = processing_pos[ia];
if (ia <= 2) {
return 0;
}
ll res = tr.query(1, processing_pos[ia - 2]);
ll pb = processing_pos[ia - 1];
res = li_pos_to[pb].val * (ia - 2) - res;
return res;
};
auto cal_right = [&](ll ia) -> ll {
if (ia >= len - 1) {
return 0;
}
ll pa = processing_pos[ia];
ll pb = processing_pos[ia + 1];
ll res = tr.query(processing_pos[ia + 2], N);
res = res - li_pos_to[pb].val * (len - ia - 1);
return res;
};
auto check1 = [&](ll p) -> bool {
// 这个程序,只要左边比右边大,就 return false
return cal_left(p) >= cal_right(p);
};
auto check2 = [&](ll p) -> bool {
// 这个程序,只要左边比右边大,就 return false
return cal_left(p) <= cal_right(p);
};
while (l < r) {
ll mid = l + r >> 1;
if (check1(mid)) {
r = mid;
} else {
l = mid + 1;
}
}
ll ans1 = l;
l = 1, r = len;
while (l < r) {
ll mid = l + r +1 >> 1;
if (check2(mid)) {
l = mid;
} else {
r = mid - 1;
}
}
ll ans2=l;
// #ifdef LOCAL
// debug(ans1);
// debug(ans2);
// debug(cal_left(ans1));
// debug(cal_right(ans2));
// #endif
ll res=min(max(cal_left(ans1),cal_right(ans1)),max(cal_right(ans2),cal_left(ans2)));
res%=mod;
res*=binpow(len-2,mod-2);
res%=mod;
return res;
};

AC代码

AC

https://codeforces.com/contest/2203/submission/364812724

心路历程(WA,TLE,MLE……)

虽然是权值线段树(树状数组),但是还是加的这个值。

image

不要搞反顺序了。

image