1 条题解
-
0
题意理解
我们有一个数组 ( a ),长度 ( n ),已经按非递减顺序排好(题目没说,但题意和标程都隐含这一点,因为用了
upper_bound并假设 ( a_x < a_y < a_z ))。Alice 要选三个下标 ( x < y < z ),对应的元素是 ( a_x, a_y, a_z )。她希望她的“红色元素”的和 ( R = a_x + a_y + a_z ) 大于 Bob 能得到的“蓝色元素”的最大和。
游戏规则(根据描述推测):
- Alice 先选三个位置,把它们染成红色。
- Bob 再行动,但题里说 Bob 有两种选择:
- 选最大元素 ( a_n )(即最后一个元素,因为排好序了)染蓝。
- 选当前红色元素中最大的 ( a_z ) 染蓝(这样 Bob 得到的蓝元素和增加 ( a_z ),但红色元素和减少 ( a_z ))。
两种选择的结果,对红色和蓝色的差距的变化不同。题解里直接给出:
Bob 会最大化自己的收益,他选
[ \max(2a_z,\ a_n) ]
为什么差距改变量是 ( \max(2a_z, a_n) )
初始时红蓝差距 = 红 - 蓝。在游戏前,Bob 还没选。Bob 有两种操作:
-
取 ( a_n ) 染蓝:
- 蓝元素和增加 ( a_n ),红色不变(因为选的是还没染色的元素)。
- 差距变化:红蓝差距 = ( R - (B + a_n) ) = 原来的差距 ( (R-B) - a_n )。
差值的减少量 = ( a_n )。
-
取 ( a_z ) 染蓝:
- 蓝增加 ( a_z ),红减少 ( a_z )(因为 ( a_z ) 原来是红色,现在转蓝)。
- 差距变化 = ( (R-a_z) - (B + a_z) = R - B - 2a_z )。 差值的减少量 = ( 2a_z )。
Bob 想让差距减小得多(让他赢),所以他选 ( \max(2a_z, a_n) ) 作为差值减少量。
Alice 获胜条件
初始时 Alice 的 R 是 ( a_x + a_y + a_z )。Bob 行动后,差距变为 [ (R - B) - \max(2a_z, a_n) ] 但是 B 初始是 0(未染色时蓝和是 0),所以初始差距就是 ( R )。
所以 Bob 行动后的差距是: [ R - \max(2a_z, a_n) ]
Alice 要这个值 > 0 才赢: [ a_x + a_y + a_z > \max(2a_z, a_n) ]
问题转化
我们要数三元组 ( (x, y, z) ) 满足:
- ( x < y < z )
- ( a_x + a_y + a_z > \max(2a_z, a_n) )
因为数组已排序,且 ( a_x + a_y ) 随 ( x, y ) 增大而增大。对固定的 ( y, z ),要找最小的 ( x ) 使得条件成立,然后所有 ( x ) 到 ( y-1 ) 都成立。
公式推导
令: [ M = \max(2a_z, a_n) ] 条件: [ a_x + a_y + a_z > M ] [ a_x > M - a_y - a_z ]
由于 ( a_x ) 随 ( x ) 增大而增大,我们只需要找第一个 ( a_x ) 大于这个阈值的位置。
对于固定的 ( j = y ) 和 ( i = z )(代码里 i 是 z 的下标),令: [ t = M - a_i - a_j ] 我们要 ( a_x > t )。
二分查找第一个 ( a_k > t ) 的位置 ( k )。
因为数组下标 0..n-1,( a_x ) 对应 ( x < j ),所以在区间 ( [0, j) ) 里找 ( a_k > t ),数量是 ( j - k )。
代码解析
int main() { int t; cin >> t; while (t--) { int n; cin >> n; vector<int> a(n); for (auto& x : a) cin >> x; long long ans = 0; for (int i = 0; i < n; ++i) { // i 是 z 的下标 for (int j = 0; j < i; ++j) { // j 是 y 的下标 int x = max(a[n - 1], 2 * a[i]) - a[i] - a[j]; int k = upper_bound(a.begin(), a.begin() + j, x) - a.begin(); ans += j - k; } } cout << ans << '\n'; } }注意:
x其实对应 ( t = M - a_i - a_j )。upper_bound(a.begin(), a.begin()+j, x)找第一个 > x 的位置。- 因为 ( a_x ) 要 > t,且 x < j,所以 k 是满足 ( a_k > t ) 的最小下标,那么 ( k, k+1, ..., j-1 ) 都满足。
数量 = ( j - k )。
复杂度
-
外层 ( O(n) ),内层 ( O(n) ) 枚举 y,z,每次二分 ( O(\log n) )
总 ( O(n^2 \log n) ),对于 ( n ) 不大(比如 2000)可行。 -
可以用双指针优化到 ( O(n^2) ),但这里标程为了清晰没做。
最终答案
[ \boxed{\text{计数满足 } a_x + a_y + a_z > \max(2a_z, a_n) \text{ 的三元组数量}} ]
其中 ( x < y < z ),数组已排序。
- 1
信息
- ID
- 6546
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 3
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者