记一个CF的坑---unordered_set
题目链接:https://codeforces.com/problemset/problem/1656/B
思路:
对序列 \(a\) : \(\{a_1,a_2,\cdots , a_n\}\) , 可进行如下操作:
\(select\ x,\ erase(a_x)\ and\ set\ a_i\ to\ a_i-a_x\)
问是否可以通过 \(n-1\) 次操作使序列 \(a\) 中剩余元素等于给定元素 \(k\)
解法:
换一种理解 , 是否存在 \(a\) 的一种排列 , 使得依次删除序列 \(a\) 中前 \(n-1\) 个元素后 , \(a_n=k\) .前三次操作的结果如下:
- \(\{a_2-a_1,a_3-a_1,a_4-a_1,\cdots,a_n-a_1\}\)
- \(\{a_3-a_2,a_4-a_2,a_5-a_2,\cdots,a_n-a_2\}\)
- \(\{a_4-a_3,a_5-a_3,a_6-a_3,\cdots,a_n-a_3\}\)
可见经过 \(n-1\) 次操作后 , 序列中剩余元素为 \(a_n-a_{n-1}\) , 故原题等价于序列 \(a\) 中是否存在\(i,j\) , 使得\(|a_i-a_j|=k\).故我们只需要遍历一遍数组 \(a\) ,判断数组中是否存在\(a_i-k\) , 若存在则必定可以获得 \(k\) , 否则无法获得 \(k\) , 于是便有了如下代码:
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int t,n,k,a;
unordered_set<int> mp;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>t;
while(t--){
cin>>n>>k;
mp.clear();
for(int i=1;i<=n;i++){
cin>>a;
mp.insert(a);
}
bool flag = 1;
for(auto i=mp.begin();i!=mp.end();i++){
if(mp.count(*i-k)>0){
flag = 0;
break;
}
}
cout<<(flag==1?"NO":"YES")<<'\n';
}
return 0;
}
直到我发现了如下文章:https://zhuanlan.zhihu.com/p/399073979?ivk_sa=1024320u
哈 ? 还有这种操作 ?
更改后的代码如下:
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int t,n,k,a;
unordered_set<int> mp;
signed main(){
int p = rand();
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>t;
while(t--){
cin>>n>>k;
mp.clear();
for(int i=1;i<=n;i++){
cin>>a;
mp.insert(a^p);
}
bool flag = 1;
for(auto i=mp.begin();i!=mp.end();i++){
if(mp.count((((*i)^p)-k)^p)>0){
flag = 0;
break;
}
}
cout<<(flag==1?"NO":"YES")<<'\n';
}
return 0;
}

浙公网安备 33010602011771号