1 条题解
-
0
题解
本题是一个博弈问题:阿里希望最小化最终价值 ,巴哈明希望最大化 。每一轮阿里选择两个下标 ,巴哈明可以任意重排 这四个数。
核心观察
对于任意两个下标 和 ,设四个数为 。不失一般性,假设排序后为 。巴哈明可以将它们重新分配给两个位置。考虑以下三种有代表性的分配方式:
-
保持不变(或等价形式):
分配为
贡献为 -
交换 和 :
分配为
贡献为 -
交换 和 (或等价形式):
分配为
贡献为
可以验证,第二种和第三种分配方式得到的价值相同,且比第一种分配方式恰好多出 。
两种情况
定义区间 (若 则交换为 ,因为绝对值只关心差的绝对值,且重排可以交换两者)。
令初始总价值为 。情况 1:存在两个区间相交(即存在 使得 )。
此时阿里可以选择这样一对相交区间对应的下标。对于这一对,四个数排序后必然满足 和 来自不同区间,从而巴哈明无法增加这一对的价值(即这一对已经处于上述第二种或第三种分配方式的形态)。阿里只需每次选择同一对相交区间,巴哈明就无法在任何一轮增加总价值。因此答案即为初始价值 。情况 2:所有区间两两不交(任意两个区间要么完全分离,要么一个包含另一个?实际上由于定义 已排序,若两两不交则它们要么分离要么包含。但若包含,则区间相交,必回到情况 1。因此情况 2 意味着所有区间两两严格分离)。
此时对于任意一对 ,四个数排序后必然呈现为两个分离区间(例如 整体小于 ),即总是处于第一种分配方式的形态。巴哈明可以在阿里选择某对下标后,将这一对变为第二种或第三种分配方式,从而使总价值在 的基础上增加 。这里的 恰好是两个区间之间的最近距离(后一区间的左端减去前一区间的右端)。阿里希望最小化增加量,因此他会选择两个最近的分离区间(即最小化 )。巴哈明会在阿里选择的那一轮执行一次重排以增加价值,之后阿里仍然只能给出分离区间,但巴哈明在后续轮次中若再次改变会使得某些区间发生相交,进而可能让阿里在后继轮次中迫使价值下降(因为一旦相交,阿里可以转而利用情况 1 阻止巴哈明),因此巴哈明在第一次增加后应停止操作(后续轮次不做改变)。所以最终答案等于:
算法实现
- 对每个 ,令 ,,形成区间 。
- 计算初始价值 。
- 将所有区间按左端点 升序排序。
- 遍历排序后的区间,检查相邻区间是否相交:
- 若存在某个相邻区间满足 (相交),则属于情况 1,答案为 。
- 若所有相邻区间均不相交(即对所有 有 ),则属于情况 2。计算最小间距 ,答案为 。
时间复杂度 ,空间复杂度 。
代码参考
#include <bits/stdc++.h> using namespace std; using ll = long long; void solve() { int n, k; cin >> n >> k; vector<ll> a(n), b(n); for (int i = 0; i < n; i++) cin >> a[i]; for (int i = 0; i < n; i++) cin >> b[i]; vector<pair<ll, ll>> segs(n); ll V0 = 0; for (int i = 0; i < n; i++) { ll l = min(a[i], b[i]); ll r = max(a[i], b[i]); segs[i] = {l, r}; V0 += r - l; } sort(segs.begin(), segs.end()); bool intersect = false; ll min_gap = LLONG_MAX; for (int i = 0; i + 1 < n; i++) { if (segs[i + 1].first <= segs[i].second) { intersect = true; break; } else { min_gap = min(min_gap, segs[i + 1].first - segs[i].second); } } if (intersect) { cout << V0 << "\n"; } else { cout << V0 + 2 * min_gap << "\n"; } } int main() { ios::sync_with_stdio(false); cin.tie(0); int t; cin >> t; while (t--) solve(); return 0; } -
- 1
信息
- ID
- 6954
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 6
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者