Number Game
题意不多赘述,可以参考洛谷的翻译。
思路:贪心地去思考,Bob每次删除序列中的最小的元素更符合Bob的最优选择,由此我们可以选择模拟这个游戏的过程,Alice每轮删除最大的x(x<=k-i+1),如果没有x那么Alice输。
好了,这是在做这道题前要整理出来的,那么接下来怎么去找出最大的k呢,由题意1<=k<=n很显然可以用二分查找去找到答案k,那么二分区间的条件显然就是Alice能不能赢,这里面我们可以对模拟的过程进行简化,由上x<=k-i+1,每次找到序列a中符合该条件最大的x,那么更大的(即序列中大于x的)显然无法去考虑,所以在处理这个过程我们可以选择双指针或模拟栈。
AC代码:
#include <bits/stdc++.h>
int main () {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int t;
std::cin >> t;
while (t--) {
int n;
std::cin >> n;
std::vector<int> a(n), b(n);
for (int &ai : a) {
std::cin >> ai;
}
std::function<int(int)> judge = [&](int x) {
b = a;
int j = x;
while (j >= 1) {
while (!b.empty() && b.back() > j) {
b.pop_back();
}
if (b.empty()) {
return 0;
}
b.pop_back();
if (!b.empty()) {
b.erase(b.begin());
}
j--;
}
return 1;
};
std::sort(a.begin(), a.end());
int l = 0, r = n + 1;
while (l + 1 < r) {
int mid = (l + r) >> 1;
if (judge(mid)) l = mid;
else r = mid;
}
std::cout << l << "\n";
}
return 0;
}