CF2165C
Solution
首先是第一个观察,就是既然 $b_i$ 可以为 $0$,而 $0$ 对异或的结果是没有影响的,所以不一定要用完 $n$ 个数。
然后要最后结果为 $k$,显然 $k$ 的每个二进制位只要有一个 $b_i$ 的这一位为 $1$ 就行。
如果 $k$ 的第 $i$ 二进制位也就是 $2^i$ 无法被任何一个 $b_i$ 取到就无法成立。所以现在要花费来使 $b_i$ 的上限变大。
肯定是贪心地选择最大的一个 $a_i$ 来使 $a_i$ 变大,然后可以取到的 $b_i$ 也就会变大,便可以覆盖到整个 $k$。
所以先把 $a$ 数组从大到小排序,枚举每一个 $2^i$,如果当前 $a$ 的值可以覆盖 $2^i$ 就直接用,否则补上并统计花费。
但是会发现这样有一个漏洞,就是比如 $a_i>2^i$,它剩下的 $a_i-2^i$ 依然可以作贡献,取最大值的时候也需要考虑,所以可以用一个优先队列来存这个用过的值,最多 $30$ 个也就是没位产生一个。
Code
#include<bits/stdc++.h>
using namespace std;
using LL=long long;
LL a[500005];
void solve(){
LL n,q;
cin>>n>>q;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1,greater<LL>());
while(q--){
LL k;
cin>>k;
LL ans=0;
priority_queue<LL,vector<LL> > q;
int j=1;
for(int i=(1<<30);i>=1;i>>=1){
if(k>=i){
LL mx;
bool from_array=false;
if(j<=n&&(q.empty()||a[j]>=q.top())){
mx=a[j];
from_array=true;
}else{
mx=q.top();
from_array=false;
}
if(mx>i){
q.push(mx-i);
k-=i;
}else{
ans+=i-mx;
//cout<<i<<' '<<mx;
k-=i;
}
if(from_array&&j<=n){
j++;
}else if(!from_array&&!q.empty()){
q.pop();
}
}
}
cout<<ans<<"\n";
}
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin>>t;
while(t--) solve();
return 0;
}