传送门:http://codeforces.com/contest/967/problem/E
题目大意:
给出n个数字(a1,a2,a3,……),问(ai,ai⊕ai+1,ai⊕ai+1⊕ai+2,……)是否能是升序的,能的话给出排列顺序。
思路:
a异或b的结果要比a大,只有2种情况(令k为b的最高位):①b的位数比a大;②b的位数比a小并且a的第k位为0。
而第一种情况也可以合并在第二种情况里,毕竟b的位数比a大那a的第k位自然为0。
有了上面的想法,首先我们记录最高位为i的有哪些数字。然后从最小的位开始找,如果满足a的第i位为0并且i为最高位的数还存在,那么就将这个数加入。反复这个行为,若最后所有数都用上了那么就成功了,否则失败。
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<utility>
#include<algorithm>
#include<utility>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<cmath>
#include<map>
#define P pair<int,int>
#define ll long long
#define INF 1e9
#define M 1e9+7
#define MAX 500010
#define lson id*2,l,mid
#define rson id*2+1,mid+1,r
using namespace std;
ll n;
ll a[100010];
vector <ll> bit[64];
ll anss[100010];
int main()
{
cin >> n;
for (int i = 0; i < n; i++)
cin >> a[i];
for (int i = 0; i < n; i++) {
int len = 0;
ll x = a[i];
while (x != 0) {
len++;
x /= 2;
}
bit[len - 1].push_back(a[i]);
}
ll ans = 0;
int cnt = 0;
while (n--) {
int i = 0;
for (; i < 60; i++) {
ll x = 1LL << i;
if ((x&ans) == 0 && !bit[i].empty()) {
ans ^= *(bit[i].end() - 1);
anss[cnt++] = *(bit[i].end() - 1);
bit[i].pop_back();
break;
}
}
if (i == 60) {
cout << "No" << endl;
return 0;
}
}
cout << "Yes" << endl;
for (int i = 0; i < cnt; i++)
cout << anss[i] << ' ';
cout << endl;
return 0;
}