题解:CF2060C Game of Mathletes
roumeideclown · · 题解
简单题。那你为什么还 Wrong answer on test 2?
这里提供一种不需要排序和双指针的解法(说实话我不太明白这题为什么会有这两个 tag)。
解法分析
此处将原题面中的序列
我们不难发现,题意等价于求在序列
例如,在序列
为什么呢?
我们称一个下标
例如,对于
然后我们就注意到对于游戏进行到任意回合,剩余的整数数量一定为偶数,「可匹配」的下标数量也一定为偶数。
那么对于一个回合,设 Alice 选择的下标为
-
若
i 是「可匹配」的,那么一定存在一个下标j 满足i \neq j 并且a_i+a_j=k ,此时 Bob 的最优策略就是选择j ,答案加一; -
若
i 不是「可匹配」的,那么也一定存在一个下标j 满足i \neq j 并且j 也不是「可匹配」的,此时 Bob 的最优策略就是选择一个不「可匹配」的下标,这样可以避免浪费掉一些「可匹配」的数,使得分数最大化。
所以题意等价于求在序列
那么如何实现呢?
我们使用一个 map 记录每个数可用(不是「可匹配」,即当前如果它没有与别的数匹配就是可用的)的数量,遍历到
代码实现
#include<bits/stdc++.h>
// #pragma G++ optimize(2)
using namespace std;
using ll=long long;
using ull=unsigned long long;
using ld=long double;
using pii=pair<int,int>;
#define fi first
#define se second
constexpr int N=2e5+5;
int a[N];
map<int,int> mp;
void solve() {
mp.clear(); // 清多测
int n,k;cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i];
int ans=0;
for(int i=1;i<=n;i++) {
if(mp[k-a[i]]>0) { // 如果有可用的 k-a[i]
mp[k-a[i]]--; // 去掉一个
ans++;
}
else mp[a[i]]++; // 无法匹配就加入可用的数
}
cout<<ans<<"\n";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t;cin>>t;
while(t--) solve();
return 0;
}