Codeforces Round #477 (rated, Div. 2, based on VK Cup 2018 Round 3) E. Big Secret

传送门:http://codeforces.com/contest/967/problem/E


题目大意:

  给出n个数字(a1,a2,a3,……),问(ai,aiai+1,aiai+1ai+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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值