2019年牛客多校第4场Bxor
链接: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; }