0%

题解 CF1971G XOUR

传送门

Solution

注意到若 aiaj<4a_i \oplus a_j < 4,则 ai>>2=aj>>2a_i>>2=a_j>>2。我们将除以四后结果相同的元素分到同一组。显然,若 aia_iaja_j 可交换,aja_jaka_k 可交换,则 aia_iaka_k 可交换。所以同一组内的所有元素可相互交换,即每一组均可内部排序。

将每一组排好序后,倒序枚举原数组,将每个元素替换成所在组内的最后一个元素,并将其从组内弹出。替换完成的新数组即为答案。

code

在 C++11 及以上版本,可用 auto 枚举 map。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <bits/stdc++.h>
#define N 200010
using namespace std;
typedef long long ll;

template <typename T> inline void read(T &x)
{
x = 0; T f = 1; char ch = getchar();
while (!isdigit(ch)) {if (ch == '-') f = -f; ch = getchar();}
while (isdigit(ch)) {x = x * 10 + ch - 48; ch = getchar();}
x *= f;
}

int T, n, a[N], ans[N];

void WORK()
{
map<int, vector<int> > mp;
read(n);
for (int i = 1; i <= n; i++) {
read(a[i]);
mp[a[i] >> 2].push_back(a[i]);
}
for (auto &[num, vec] : mp)
sort(vec.begin(), vec.end());
for (int i = n; i; i--) {
ans[i] = mp[a[i] >> 2].back();
mp[a[i] >> 2].pop_back();
}
for (int i = 1; i <= n; i++)
printf("%d ", ans[i]);
putchar('\n');
}

int main()
{
read(T);
while (T--) WORK();
return 0;
}