题目链接https://ac.nowcoder.com/acm/contest/884/B
题意
给出n个集合,q个询问。每次询问一个区间,问区间内的集合是否有一个子集异或得到询问的值。
题解
官方题解
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e4+7;
struct Node{
ll v[50];
void init(){
for(int i=0;i<50;i++) v[i]=0;
}
void add(ll x){
for(int i=32;i>=0;i--){
if(x&(1ll<<i)){
if(!v[i]){v[i]=x;break;}
x^=v[i];
}
}
}
bool ask(ll x){
for(int i=32;i>=0;i--){
if(x&(1ll<<i)) x^=v[i];
}
return x==0ll;
}
Node cross(Node k){
Node res,tmp=k;
res.init();
for(int i=0;i<=32;i++){
ll x=v[i],y=0;
bool flag=false;
for(int j=32;j>=0;j--){
if((x>>j)&1){
if(k.v[j]) x^=k.v[j],y^=tmp.v[j];
else{
k.v[j]=x;
tmp.v[j]=y;
flag=true;
break;
}
}
}
if(!flag) res.v[i]=y;
}
return res;
}
}t[N<<2];
vector<ll>vc[N];
int n,m;
void bd(int rt,int l,int r){
t[rt].init();
if(l==r){
int sz=vc[l].size();
for(int i=0;i<sz;i++){
t[rt].add(vc[l][i]);
}
return;
}
int m=l+r>>1;
bd(rt<<1,l,m);
bd(rt<<1|1,m+1,r);
t[rt]=t[rt<<1].cross(t[rt<<1|1]);
}
bool que(int rt,int l,int r,int L,int R,ll x){
if(L<=l&&r<=R) return t[rt].ask(x);
int m=l+r>>1;
bool ret=true;
if(L<=m) ret=ret&que(rt<<1,l,m,L,R,x);
if(m<R) ret=ret&que(rt<<1|1,m+1,r,L,R,x);
return ret;
}
int main(){
scanf("%d%d",&n,&m);
ll x;
for(int i=1,sz;i<=n;i++){
scanf("%d",&sz);
for(int j=1;j<=sz;j++){
scanf("%lld",&x);
vc[i].push_back(x);
}
}
bd(1,1,n);
for(int i=1,l,r;i<=m;i++){
scanf("%d%d%lld",&l,&r,&x);
if(que(1,1,n,l,r,x)) printf("YES\n");
else printf("NO\n");
}
}