题解 [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;
}