题目描述:
你有一个由非负整数构成的数组。只要
a
i
⊕
a
j
<
4
a_i \oplus a_j<4
ai⊕aj<4,你就可以交换它们的位置。问:你可以如何通过任意次数的交换,得到上最小的数组?
这里“最小”是指在比较两个数组时,从左到右找到的第一个不同位置上,
a
i
的值小于
b
i
的值
a_i的值小于b_i的值
ai的值小于bi的值。
思路:
写出所有 1 − 9 的二进制发现 , 若 a i ⊕ a j < 4 , 只需要保证二进制的前两位异或为 0 即可 根据异或的性质可知 , a ⊕ a = 0 , 故相当于保证前两位相等 如 9 = 1001 , 8 = 1000 , 它们前两位为 10 , 10 相等 , 可以交换 用一个优先队列哈希表存一下能够交换的最小值 , 贪心即可 写出所有1-9的二进制发现,若a_i\oplus a_j<4,只需要保证二进制的前两位异或为0即可\\ 根据异或的性质可知,a\oplus a=0,故相当于保证前两位相等\\ 如9=1001,8=1000,它们前两位为10,10相等,可以交换\\ 用一个优先队列哈希表存一下能够交换的最小值,贪心即可\\ 写出所有1−9的二进制发现,若ai⊕aj<4,只需要保证二进制的前两位异或为0即可根据异或的性质可知,a⊕a=0,故相当于保证前两位相等如9=1001,8=1000,它们前两位为10,10相等,可以交换用一个优先队列哈希表存一下能够交换的最小值,贪心即可
代码:
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int a[N];
int t,n;
int main(){
cin >> t;
while(t--){
cin >> n;
map<int,priority_queue<int>> mp;
for(int i=0;i<n;i++){
cin >> a[i];
mp[a[i]>>2].push(-a[i]);
//将xor小于4的值的负数加入
//要最小值,优先队列默认是大根堆,加负数相当于使用小根堆
//当然可以直接用greater<int>
}
for(int i=0;i<n;i++){
//将能xor中最小值输出
cout << -mp[a[i]>>2].top() << " ";
mp[a[i]>>2].pop();
}
cout << endl;
}
return 0;
}