时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 524288K,其他语言1048576K
链接:https://ac.nowcoder.com/acm/contest/884/B
来源:牛客网
分数:2500 我觉得是常规的数据结构题(
题目描述
Your are given
n
n
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
l,r,x
l,r,x and you should answer if for every
i
∈
[
l
,
r
]
i∈[l,r]
i∈[l,r],the i-th set can express
x
x
x.
输入描述:
The first line contains two integers
n
,
m
n,m
n,m.
For each of the following
n
n
n lines, the first integer
s
z
sz
sz stands for the size of this set and the following
s
z
sz
sz integers stand for the elements in this set. The sets are described from number
1
1
1 to
n
n
n.
For each of the following
m
m
m lines, there’re three integers
l
,
r
,
x
l,r,x
l,r,x that means a query.
输出描述:
For each query, output a line.
If for every
i
∈
[
l
,
r
]
i∈[l,r]
i∈[l,r] ,the i-th set can express
x
x
x, you need to print “YES”, and “NO” otherwise.
示例1
输入
复制
1 3
2 1 2
1 1 0
1 1 3
1 1 4
输出
复制
YES
YES
NO
备注:
1 ≤ n , m ≤ 50000 , 1 ≤ s z ≤ 32 , 1 ≤ l ≤ r ≤ n 1 \le n,m \le 50000 ,1 \le sz \le 32,1 \le l \le r \le n 1≤n,m≤50000,1≤sz≤32,1≤l≤r≤n,the every integer in input ∈ [ 0 , 2 32 ) \in [0,2^{32}) ∈[0,232)。
题意:
给定n个集合,每次询问一个区间
l
,
r
l,r
l,r和一个数字
x
x
x,询问从集合
l
l
l到
r
r
r中,是否每个集合都可以满足
x
x
x是若干个集合元素的异或和。
题解:
对于一个集合来说,我们可以把这个集合用线性基来表示,然后对于一个区间,我们可以求出这个区间的线性基的交集,然后将直接对这个交集询问
x
x
x即可
#include<bits/stdc++.h>
#define uint unsigned int
#define ll long long
using namespace std;
struct lb{
ll b[34];
void CLEAR(){
memset(b,0,sizeof(b));
}
bool ins(ll x){
for(int i=31;i>=0;i--){
if(x&(1LL<<i)){
if(!b[i]){
b[i]=x;
break;
}
x^=b[i];
}
}
return x!=0;
}
bool check(ll x){
for(int i=31;i>=0;i--){
if(x&(1LL<<i)){
if(b[i])x^=b[i];
else return 0;
}
}
return 1;
}
};
struct seg{
int l,r;
lb lin;
}tr[200004];
int n,m;
void update(int k){//线性基求交集
lb a=tr[k<<1|1].lin,b=tr[k<<1|1].lin;
for(int i=0;i<32;i++){
if(!tr[k<<1].lin.b[i])continue;
ll temp=0,x=tr[k<<1].lin.b[i];
int j;
for(j=i;j>=0;j--){
if(x&(1LL<<j)){
if(a.b[j]){
x^=a.b[j];
temp^=b.b[j];
}
else break;
}
}
if(x==0)tr[k].lin.b[i]=temp;
else{
a.b[j]=x;
b.b[j]=temp;
}
}
}
void build(int k,int l,int r){
tr[k].l=l;tr[k].r=r;
tr[k].lin.CLEAR();
if(l==r){
int sz;
ll x;
scanf("%d",&sz);
for(int i=1;i<=sz;i++){
scanf("%lld",&x);
tr[k].lin.ins(x);
}
return ;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
update(k);
}
bool query(int k,int a,int b,ll x){
int l=tr[k].l,r=tr[k].r;
if(a==l&&r==b){
return tr[k].lin.check(x);
}
int mid=(l+r)>>1;
if(b<=mid)return query(k<<1,a,b,x);
else if(a>mid)return query(k<<1|1,a,b,x);
else{
return query(k<<1,a,mid,x)&&query(k<<1|1,mid+1,b,x);
}
}
int w33ha(){
build(1,1,n);
while(m--){
int l,r;ll x;
scanf("%d%d%lld",&l,&r,&x);
bool t=query(1,l,r,x);
if(t)puts("YES");
else puts("NO");
}
return 0;
}
int main(){
while(scanf("%d%d",&n,&m)!=EOF)w33ha();
return 0;
}