其他分享
首页 > 其他分享> > CF1715D 2+ doors

CF1715D 2+ doors

作者:互联网

简要题意

对于一个数组 \(a\),给定 \(Q\) 个限制条件,每个条件给出 \(i,j,x\) 使得 \(a_i|a_j=x\)。

构造数组使其字典序最小。

Solution

以下 \(ans_i\) 表示最后我们构造出来的答案数组。

考虑一个最宽松的限制条件,我们有一个 \(b\) 数组,在最开始,\(b\) 在二进制意义下全是 \(1\)。

对于每个条件,我们令 \(b_i=b_i\&x,b_j=b_j\&x\)。

显然,\(b\) 数组是答案最宽松的条件,即 \(ans_i\subseteq b_i\)。

也就是说,若一定存在解,则 \(b_i\) 必然是一组合法解。

现在要求字典序最小,我们从前往后构造答案。

考虑当前构造位 \(i\)。

为了让字典序最小,对于一个限制 \(\{a_i|a_j=x,(i<j)\}\),我们应尽可能的让 \(ans_j\) 完成要求,\(ans_j\) 能完成的部分即为 \(x\&b_j\)。

剩余的部分,即 \((x\) \(^\) \((x\&b_j))\),则不得不让 \(ans_i\) 来完成,于是 \(ans_i\) 必须或上这一部分。

但是注意,\(ans_j\) 并不是一定要完成 \(x\&b_j\)。

因为 \(ans_i\) 也有可能在其他条件的迫害下不得不完成了一部分 \(x\)。

于是我们对于 \(\{a_i|a_j=x,(i>j)\}\),再让 \(ans_i|=(x\&ans_i)\) 来完成剩余的限制即可。

由于每一步都是必要的,所以他是最小的。

至于 \(\{a_i|a_j=x,(i=j)\}\),则 \(ans_i=x\) 是必然的。

复杂度 \(O(n+q)\)。

#include<bits/stdc++.h>
#include<vector>
const int N=200010;
int a[N],b[N],ans[N];
struct node{
	int to,val;
};
std::vector<node>p[N];
signed main(){
	int n,q;
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++)a[i]=(1<<30)-1;
	int x,y,z;
	for(int i=1;i<=q;i++){	
		scanf("%d%d%d",&x,&y,&z);
		a[x]=z&a[x],a[y]=z&a[y];
		p[x].push_back(node{y,z}),p[y].push_back(node{x,z});
	}
	for(int i=1;i<=n;i++){
		for(node j:p[i]){
			if(i==j.to)ans[i]|=j.val;
			else if(j.to>=i){
				ans[i]|=((j.val^(j.val&a[j.to]))&a[i]);
			}
			else {
				ans[i]|=((j.val^(j.val&ans[j.to]))&a[i]);
			}
		}
	}
	for(int i=1;i<=n;i++)printf("%d ",ans[i]);
	return 0;
}

标签:doors,val,int,条件,CF1715D,数组,ans,字典
来源: https://www.cnblogs.com/Qzong/p/16609259.html