题意:求区间线性基的交,然后判断是否能异或出x
暂时不理解,先当个板子记了~回来有空再看看
#include<bits/stdc++.h>
#define lc o*2
#define rc o*2+1
#define ll long long
using namespace std;
const int maxn = 50005;
const int size = 32;
ll base[4*maxn][32];
int n,m;
vector<ll>V[maxn];
void insert(int o,ll x){
for(int i=size-1;i>=0;i--){
if((x>>i)&1){
if(base[o][i]){
x^=base[o][i];
}else{
base[o][i]=x;
break;
}
}
}
}
void pushup(int o) {
ll t1[size],t2[size];//t1->b1和b2的并,t2->表示新的线性基每一位由b1的那些做贡献
for(int i=0; i<size; i++)t1[i]=t2[i]=base[lc][i];
for(int i=0; i<size; i++) {
if(base[rc][i]) { //从低位到高位枚举b
ll now=0,d=base[rc][i];//目前由b1造成的贡献,将d插入线性基
for(int j=i; j>=0; j--) {
if((d>>j)&1) {
if(t1[j]) {
d^=t1[j],now^=t2[j];//维护b2异或的b1部分
if(d)continue;
base[o][i]=now;//将b1部分直接插入线性基当中
//insert(o,now);
} else {
t1[j]=d;
t2[j]=now;
}
break;
}
}
}
}
}
void build(int o,int L,int R){
if(L==R){
for(auto t:V[L])
insert(o,t);
return;
}
int M=(L+R)>>1;
build(lc,L,M);
build(rc,M+1,R);
pushup(o);
}
bool query(int o,int L,int R,int ql,int qr,int x){
if(ql<=L&&R<=qr){
ll d=x;
for(int i=size-1;i>=0;i--){
if((d>>i)&1){
if(!base[o][i])return false;
else{
d^=base[o][i];
}
}
}
return true;
}
int M=(L+R)>>1;
if(ql<=M){
if(!query(lc,L,M,ql,qr,x))return false;
}
if(qr>M){
if(!query(rc,M+1,R,ql,qr,x))return false;
}
return true;
}
int main() {
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
int t;scanf("%d",&t);
for(int j=1;j<=t;j++){
ll tmp;scanf("%lld",&tmp);
V[i].push_back(tmp);
}
}
build(1,1,n);
while(m--){
int l,r;ll x;scanf("%d%d%lld",&l,&r,&x);
puts(query(1,1,n,l,r,x)?"YES":"NO");
}
return 0;
}