CF 1715 D. 2+ doors 位运算 1900

12 篇文章 0 订阅

题意:一个长度为 n 的数组 a,有 q 个条件,每个条件有 3 个整数 i,j,x,表示 ai | aj = x。找出满足条件的最小字典序的数组 a。

思路:用二进制看每个数,通过 ai | aj = x,我们不能确定第 i 个数和第 j 个数哪一位是 1,但能确定哪些位一定是 0,所以我们可以求出每个数的最大值是和这个位置有关的 x 全部 & 在一起,我们用一个数组 f 来维护每个数最多能贡献多少。然后从小到大遍历数组 a,每次遍历确定一个数,假设当前遍历到第 i 个数,再遍历所有与 i 有关的 j 和 x,如果 j > i,那么尽量要让 aj 来贡献出 x,aj 可以贡献的部分是 f j & x,不能贡献的部分是 ~f j & x,那么这部分就需要 ai 来提供,如果 j < i,aj已经是确定的最小值,所以 aj 不能贡献的部分为 ~ aj & x, 这部分同样需要 ai 来提供,所以 ai 的值就是把这些需要 ai 来提供的部分 | 在一起。

代码:

#include<bits/stdc++.h>
#define pb push_back
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 2e5 + 10, P = 1e9 + 7, mod = 998244353;
void solve(){
	int n, q;
	cin >> n >> q;
	vector<int> f(n + 1, (1 << 30) - 1);
	vector<PII> v[n + 1];
	for(int i = 1; i <= q; i++) {
		int a, b, c;
		cin >> a >> b >> c;
		f[a] &= c, f[b] &= c;
		v[a].pb({b, c});
		v[b].pb({a, c});
	}
	for(int i = 1; i <= n; i++){
		int t = 0;
		for(auto p : v[i]) {
			int j = p.first, x = p.second;
			t |= x & ~f[j];
			if(j == i) t = x;
		}
		f[i] = t;
		cout << t << " ";
	}
}                
int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int tt;
	//cin >> tt;
	//while(tt--) {
		solve();
	//}
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值