传送门: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代码:
扫描二维码关注公众号,回复:
708510 查看本文章
#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; }