题解 [CSP-S2020] 动物园

传送门

补道以前的题
首先可以对每一位开个bitset记录下选这一位需要哪些饲料
然后 \(O(64)\) 扫一遍就好了,注意可能会爆ull所以我开了int128

但其实有个空间复杂度更优的做法
发现保证 \(q_i\) 互不相同,所以这玩意没用
然后考虑哪些 \(q_i\) 可以被选就可以了

Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 1000010
#define ll long long
#define int __int128

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans;
}

int n, m, c, k, s;
int a[N], uni[N], usize, p[N], q[N], one=1, top;
bitset<N> lim[70], buy;
char sta[N];
void write(__int128 t) {
	top=0;
	do {sta[++top]='0'+t%10; t/=10;} while (t);
	while (top) putchar(sta[top--]);
	printf("\n");
}

signed main()
{
	n=read(); m=read(); c=read(); k=read();
	for (int i=1; i<=n; ++i) a[i]=read(), s|=a[i];
	for (int i=1; i<=m; ++i) {
		p[i]=read(); q[i]=read();
		uni[++usize]=q[i];
	}
	sort(uni+1, uni+usize+1);
	usize=unique(uni+1, uni+usize+1)-uni-1;
	for (int i=1; i<=m; ++i) q[i]=lower_bound(uni+1, uni+usize+1, q[i])-uni;
	for (int i=1; i<=m; ++i) {
		if (s&(one<<p[i])) buy[q[i]]=1;
		lim[p[i]][q[i]]=1;
	}
	int ans=1;
	for (int i=0; i<k; ++i) {
		if ((lim[i]&buy)==lim[i]) ans<<=1;
	}
	// printf("%llu\n", ans-n);
	write(ans-n);

	return 0;
}
posted @ 2021-10-24 21:15  Administrator-09  阅读(4)  评论(0编辑  收藏  举报