链接:https://ac.nowcoder.com/acm/contest/884/B
来源:牛客网
题目描述
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.
线段树+线性基求交。
题意:
给出n个集合。每个集合有一些数,第一个数k为该集合大小,然后是k个数。
m次询问,每次给出l.r.x问是否在l~r区间内,每一个区间是否都可以由任意个数异或出x。
思路:
用线段树维护一个区间线性基的交,对于每一次询问看维护的线性基的交是否可以异或出x就可以了。
有关线性基求交的博客:https://blog.csdn.net/demon_rieman/article/details/88830846
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll maxbit=31;
const ll maxn=5e4+5;
struct node
{
ll l,r;
ll basis[maxbit+3];
void clean()
{
l=0,r=0;
for(ll i=0;i<=maxbit;i++)
basis[i]=0;
return ;
}
void in(ll k)
{
for(ll i=maxbit;i>=0;--i)
{
if((k>>i)&1)
{
if(basis[i])
{
k^=basis[i];
} else {
basis[i]=k;
break;
}
}
}
return ;
}
}tree[maxn<<3];
node Union(node A,node B)
{
node All,C,D;
All.clean();
C.clean();
D.clean();
for(ll i=maxbit; i>=0; --i)
{
All.basis[i]=A.basis[i];
D.basis[i] = 1ll << i;
}
for(ll i=maxbit; i>=0; --i)
{
if(B.basis[i])
{
ll v=B.basis[i],k=0;
bool can = true;
for(ll j=maxbit; j>=0; --j)
{
if((v>>j)&1)
{
if(All.basis[j])
{
v^=All.basis[j];
k^=D.basis[j];
}
else
{
can=false;
All.basis[j] = v;
D.basis[j] = k;
break;
}
}
}
if(can)
{
ll v=0;
for(ll j=maxbit; j>=0; --j)
{
if((k>>j)&1)v^=A.basis[j];
}
C.in(v);
}
}
}
return C;
}
void build(ll l,ll r,ll rt)
{
if(l==r)
{
ll k;
scanf("%lld",&k);
ll val;
tree[rt].clean();
tree[rt].l=l;tree[rt].r=r;
for(ll i=1;i<=k;i++) {scanf("%lld",&val);tree[rt].in(val);}
return ;
}
// cout<<l<<"_____"<<r<<"_______"<<rt<<endl;
ll mid=(l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
tree[rt].clean();
tree[rt]=Union(tree[rt<<1],tree[rt<<1|1]);
tree[rt].l=l;tree[rt].r=r;
return ;
}
bool seek_wa(ll x,ll rt)
{
for(ll i=maxbit;i>=0;--i)
{
if((x>>i)&1)
{
if(tree[rt].basis[i]) x^=tree[rt].basis[i];
else return false ;
}
}
if(x==0) return true;
return false;
}
bool seek_ans( ll sl,ll sr,ll x,ll rt)
{
ll l=tree[rt].l,r=tree[rt].r;
if(sl<=tree[rt].l&&tree[rt].r<=sr)
{
if(seek_wa(x,rt)) return true;
return false;
}
//cout<<l<<" "<<r<<" "<<rt<<endl;
ll mid = (l+r)>>1;
if(sr<=mid)
{
if(seek_ans(sl,sr,x,rt<<1)) return true;
return false;
}
else if(mid<sl)
{
if( seek_ans(sl,sr,x,rt<<1|1)) return true;
return false;
}
else
{
if(seek_ans(sl,mid,x,rt<<1)&&seek_ans( mid+1,sr,x,rt<<1|1))return true;
return false;
}
return true;
}
int main()
{
ll n,m;
cin>>n>>m;
build(1,n,1);
ll l,r,x;
for(ll i=0;i<m;i++)
{
scanf("%lld%lld%lld",&l,&r,&x);
bool f=seek_ans(l,r,x,1);
if(f) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}