链接: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.
输入描述:
The first line contains two integers n,m. For each of the following n lines, the first integer sz stands for the size of this set and the following sz integers stand for the elements in this set. The sets are described from number 1 to n. For each of the following m lines, there're three integers l,r,x that means a query.
输出描述:
For each query, output a line. If for every i∈[l,r]i \in [l,r]i∈[l,r] ,the i-th set can express 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≤500001 \le n,m \le 500001≤n,m≤50000 ,1≤sz≤321 \le sz \le 321≤sz≤32,1≤l≤r≤n1 \le l \le r \le n1≤l≤r≤n ,the every integer in input ∈[0,232)\in [0,2^{32})∈[0,232)。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 100005;
class BASE {
static const int DEG = 35;
public:
int tot = 0, n = 0, cnt = 0;
ll d[63], nd[63];
BASE() {
memset(d, 0, sizeof d);
tot = 0; n = 0; cnt = 0;
}
~BASE() {}
void Init() {
memset(d, 0, sizeof d);
tot = 0; n = 0; cnt = 0;
}
void Ins(ll x) {
n++;
for (int i = DEG; i >= 0; i--) {
if (x >> i) {
if (!d[i]) { d[i] = x; cnt++; break; }
x ^= d[i];
}
}
}
ll Max(ll x) {
ll res = x;
for (int i = DEG; i >= 0; i--) {
res = max(res, res^d[i]);
}
return res;
}
ll Min() {
for (int i = 0; i <= DEG; i++)
if (d[i])
return d[i];
return 0;
}
void Rebuild() {
for (int i = DEG; i >= 0; i--) {
if (d[i] == 0)continue;
for (int j = i - 1; j >= 0; j--) {
if (d[j] == 0)continue;
if (d[i] & (1ll << j)) d[i] ^= d[j];
}
}
for (int i = 0; i <= DEG; i++)
if (d[i]) nd[tot++] = d[i];
}
ll Kth(ll k) {
if (k == 1ll && tot < n)return 0;
if (tot < n)k--;
if (k >= (1ll << tot)) return -1;
ll res = 0;
for (int i = DEG; i >= 0; i--)
if (k&(1ll << i))
res ^= nd[i];
return res;
}
bool find(ll x) {
for (int i = DEG; i >= 0; i--) {
if (x >> i) {
if (d[i] == 0) return 0;
x ^= d[i];
}
}
return 1;
}
void Merge(BASE T) {//不一定对~~hh还没题目实践
for (int i = DEG; i >= 0; i--) {
if (T.d[i] == 0)continue;
Ins(T.d[i]);
}
}
friend BASE cross(BASE a, BASE b) {
BASE c = a, res;
ll r[63];
for (int i = 0; i <= DEG; i++)
r[i] = a.d[i];
for (int i = DEG; i >= 0; i--)
{
ll x = b.d[i], s = 0;
for (int j = DEG; j >= 0; j--)
if (x >> j) {
if (c.d[j] == 0) { c.d[j] = x; r[j] = s; s = 0; break; }
x ^= c.d[j]; s ^= r[j];
}
if (s) res.Ins(s);
}
return res;
}
};
BASE a[maxn * 4 + 5];
void pushup(int rt){
a[rt] = cross(a[rt * 2], a[rt * 2 + 1]);
}
void build(int l, int r, int rt){
if (l == r){
int sz; scanf("%d", &sz);
while (sz--){
ll x; scanf("%lld", &x); a[rt].Ins(x);
}
return;
}
int mid = (l + r) >> 1;
build(l, mid, rt * 2);
build(mid + 1, r, rt * 2 + 1);
pushup(rt);
}
bool ask(int i, int l, int r, int ql, int qr, ll x){
if (ql <= l && r <= qr) return a[i].find(x);
if (r < ql || qr < l) return 1;
int mid = (l + r) >> 1;
return ask(i * 2, l, mid, ql, qr, x) && ask(i * 2 + 1, mid + 1, r, ql, qr, x);
}
int main(){
int n, m; scanf("%d%d", &n, &m);
build(1, n, 1);
while (m--){
int l, r; ll x; scanf("%d%d%lld", &l, &r, &x);
puts(ask(1, 1, n, l, r, x) ? "YES" : "NO");
}
return 0;
}