Loading

【题解】ARC141D Non-divisible Set

给定 \(N\) 个数的集合,对于每个数 \(A_i\) 求出是否存在一个大小为 \(M\) 的包含 \(A_i\) 的子集是好的。一个集合是好的当且仅当不存在两个数 \(a,b\in S,a\neq b,a|b\)\(M \le N\le 2M\)

这道题的关键点在于 \(M \le N \le 2M\) 的条件,这一步几乎占这题的 \(80\%\)

构造,我们考虑对于 \(1 \sim 2M\) 中选出 \(M\) 个数,我们将每个数写成 \((x,y)\) 表示 \(A_i = x\times 2^y\),那么然后将数塞进桶 \(x\) 中,那么我们发现每个桶中只能选一个且恰好选一个,因为桶的个数就是奇数个数为 \(M\)

接下来就很套路了,如果两个桶 \(a = kb\),那么 \(b\) 桶中选的数一定大于 \(a\) 桶选的数。那么我们可以贪心求出每个桶中能取得最大值/最小值。时间复杂度 \(\mathcal{O}(N\ln N)\)

#define N 600006
int n, m, a[N], g[N], w[N], v[N], f[N];
vector<int>c[N];
void ret(){
	while(n--)puts("No");
	exit(0);
}
int main() {
	read(n, m), m <<= 1;
	rp(i, n){
		int x; read(x), a[i] = x;
		int y = __builtin_ctz(x);
		c[x >> y].pb(y);
	}
	rp(i, m)if((i & 1) && c[i].empty())ret();
	memset(w, ~0, sizeof(w));
	memset(g, ~0, sizeof(g));
	pr(i, m)if(i & 1){
		for(int j = i + i; j <= m; j += i)cmx(w[i], g[j]);
		if(w[i] >= c[i].back())ret();
		g[i] = *upper_bound(c[i].begin(), c[i].end(), w[i]);
	}
	memset(g, ~0, sizeof(g));
	memset(f, 0x3f, sizeof(f));
	rp(i, m)if(i & 1){
		if(f[i] <= c[i].front())ret();
		g[i] = *--lower_bound(c[i].begin(), c[i].end(), f[i]);
		for(int j = i + i; j <= m; j += i)cmn(f[j], g[i]);
	}
	rp(i, n){
		int y = __builtin_ctz(a[i]);
		int x = a[i] >> y;
		if(y > w[x] && y < f[x])puts("Yes");
		else puts("No");
	}
	return 0;
}
posted @ 2022-05-29 22:58  7KByte  阅读(119)  评论(0编辑  收藏  举报