2019牛客暑期多校训练营(第四场) B Xor(线段树+线性基合并)

链接: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;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值