题目链接:https://ac.nowcoder.com/acm/contest/884/B
链接:https://ac.nowcoder.com/acm/contest/884/B
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 524288K,其他语言1048576K
64bit IO Format: %lld
空间限制:C/C++ 524288K,其他语言1048576K
64bit IO Format: %lld
题目描述
Your are given n sets.Every set contains some integers.
We say a set can express an integer, only when there exists a subset of the set such that the bitwise-xor of the elements in the subset is equal to that integer.
Now you need to answer m queries. Each query will give you three integers l,r,x and you should answer if for every i∈[l,r]i in [l,r]i∈[l,r] ,the i-th set can express x.
We say a set can express an integer, only when there exists a subset of the set such that the bitwise-xor of the elements in the subset is equal to that integer.
Now you need to answer m queries. Each query will give you three integers l,r,x and you should answer if for every i∈[l,r]i in [l,r]i∈[l,r] ,the i-th set can express x.
输入描述:
The first line contains two integers n,m.
For each of the following n lines, the first integer sz stands for the size of this set and the following sz integers stand for the elements in this set. The sets are described from number 1 to n.
For each of the following m lines, there're three integers l,r,x that means a query.
输出描述:
For each query, output a line.
If for every i∈[l,r]i in [l,r]i∈[l,r] ,the i-th set can express x, you need to print “YES”, and "NO" otherwise.
备注:
1≤n,m≤500001 le n,m le 500001≤n,m≤50000 ,1≤sz≤321 le sz le 321≤sz≤32,1≤l≤r≤n1 le l le r le n1≤l≤r≤n ,the every integer in input ∈[0,232)in [0,2^{32})∈[0,232)。
思路:问一个集合挑选出一些数是否能异或为一个数,显然是线性基。 但是题目要求l,r区间内所有集合都要查询,所以暴力显然行不通
那么区间查询显然会想到线段树,维护区间, 这里介绍一下线性基的交,看了代码,自己也不是很懂。 以后真的碰到要用到线性基的交就只能靠板子了。 线段树维护区间的交
这样就能区间查询是否能异或出某个数了。整体就这样了
线性基合并过程:
看代码:
#include<iostream> #include<cstring> #include<cstdio> using namespace std; typedef long long LL; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 const int maxn=50000+5; struct Basis { Basis() { memset(basis,0,sizeof(basis)); } LL basis[35]; void Update(LL x)//求线性基 { for(LL i=32;i>=0;i--) { if(x&(1ll<<i)) { if(!basis[i]) { basis[i]=x;break; } x^=basis[i]; } } } bool Ask(LL x) { for(LL i=32;i>=0;i--) { if(x&(1ll<<i)) { if(basis[i]) x^=basis[i]; else return false; } } return true; } }a[maxn],T[maxn<<2]; void Push_up(LL rt)//线性基的合并 { Basis tmp=T[rt<<1],v1=T[rt<<1],v2=T[rt<<1|1]; for(LL i=0;i<32;i++) { if(v2.basis[i]) { bool flag=true; LL x=v2.basis[i],now=0; for(LL j=31;j>=0;j--) { if(x&(1ll<<j)) { if(!tmp.basis[j]) { flag=false; tmp.basis[j]=x; v1.basis[j]=now; break; } x^=tmp.basis[j];now^=v1.basis[j]; } } if(flag) T[rt].Update(now); } } } void Build(LL l,LL r,LL rt) { if(l==r) { T[rt]=a[l];return ; } LL mid=(l+r)>>1; Build(l,mid,rt<<1);Build(mid+1,r,rt<<1|1);Push_up(rt); } bool Query(LL l,LL r,LL rt,LL L,LL R,LL x) { bool flag=true; if(L<=l&&r<=R) return T[rt].Ask(x); LL mid=(l+r)>>1; if(L<=mid) flag&=Query(l,mid,rt<<1,L,R,x); if(R>mid) flag&=Query(mid+1,r,rt<<1|1,L,R,x); return flag; } int main() { LL N,M; cin>>N>>M; for(LL i=1;i<=N;i++) { LL len;cin>>len; for(LL j=1;j<=len;j++) { LL x;cin>>x;a[i].Update(x); } } Build(1,N,1); while(M--) { LL l,r,x;cin>>l>>r>>x; if(Query(1,N,1,l,r,x)) printf("YES "); else printf("NO "); } return 0; }