zoukankan      html  css  js  c++  java
  • 2019牛客暑期多校训练营四 B-xor(线性基求交)

    题意:

    给出 (n) 个序列从 (1)(n),以及 (m) 个询问,每次询问所有 ([l,r]) 区间的序列是否能异或出 (x)

    分析:

    对于 ([l,r]) 区间序列来说,要判断是不是都能异或出 (x),可以求出 ([l,r]) 区间的序列的线性基的交集,然后在这个交集判断即可,那么:
    (n) 个序列的线性基建线段树,pushup 时对左右叶子做一次线性基求交。
    询问用线段树判断区间交的线性基能否插入 (x),如果能插入则说明这段区间无法异或出 (x),反之可以。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    
    const int N = 50000 + 5;
    
    struct Base {
    	
    	static const int maxN = 31;//int-31 or long long-62
    	
    	int tot, flag;
    	int d[maxN + 5];
    	int nd[maxN + 5];//used for kth
    	
    	Base() {
    		tot = flag = 0;
    		memset(d, 0, sizeof d);
    		memset(nd, 0, sizeof nd);
    	}
    
    	bool ins(LL x) {
    		for (int i = maxN; ~i; i--) {
    			if (x & (1LL << i)) {
    				if (d[i]) {
    					x ^= d[i];
    				} else {
    					d[i] = x;
    					return true;
    				}
    			}
    		}
    		flag = 1;
    		return false;
    	}
    	
    	bool canIns(LL x) {
    		for (int i = maxN; ~i; i--) {
    			if (x & (1LL << i)) {
    				if (d[i]) {
    					x ^= d[i];
    				} else {
    					return true;
    				}
    			}
    		}
    		return false;
    	}
    
    	LL queryMax() {
    		LL ans = 0;
    		for (int i = maxN; ~i; i--) ans = max(ans, ans ^ d[i]);
    		return ans;
    	}
    
    	LL queryMin() {
    		for (int i = 0; i <= maxN; i++) if (d[i]) return d[i];
    		return -1LL;
    	}
    
    	void rebuild() {
    		for (int i = maxN; ~i; i--) {
    			for (int j = i - 1; ~j; j--) {
    				if (d[i] & (1LL << j)) d[i] ^= d[j];
    			}
    		}
    		for (int i = 0; i <= maxN; i++) if (d[i])
    				nd[tot++] = d[i];
    	}
    
    	LL kth(LL k) {
    		if (flag) k--;
    		if (!k) return 0LL;
    		if (k >= (1LL << tot)) return -1LL;
    		LL ans = 0;
    		for (int i = maxN; ~i; i--) {
    			if (k & (1LL << i)) ans ^= nd[i];
    		}
    		return ans;
    	}
    
    	void merge(Base b) {//与b取并集
    		for (int i = maxN; ~i; i--) if (b.d[i])
    				ins(b.d[i]);
    	}
    
    	Base mixed(Base B) {//与b取交集
    		Base All, C, D;
    	//	All.init(), C.init(), D.init();
    		for (int i = maxN; ~i; i--) {
    			All.d[i] = d[i];
    			D.d[i] = 1LL << i;
    		}
    		for (int i = maxN; ~i; i--) {
    			if (B.d[i]) {
    				LL v = B.d[i], k = 0;
    				bool can = true;
    				for (int j = maxN; ~j; j--) {
    					if (v & (1LL << j)) {
    						if (All.d[j]) {
    							v ^= All.d[j];
    							k ^= D.d[j];
    						} else {
    							can = false;
    							All.d[j] = v;
    							D.d[j] = k;
    							break;
    						}
    					}
    				}
    
    				if (can) {
    					LL v = 0;
    					for (int j = maxN; ~j; j--) {
    						if (k & (1LL << j)) {
    							v ^= d[j];
    						}
    					}
    					C.ins(v);
    				}
    			}
    		}
    		return C;
    	}
    
    } lb[N << 2];
    
    int n, m, sz, l, r, x;
    
    void build(int rt, int l, int r) {
    	if (l == r) {
    		scanf("%d", &sz);
    		for (int i = 1; i <= sz; i++) {
    			scanf("%d", &x);
    			lb[rt].ins(x);
    		}
    		return ;
    	}
    	int mid = l + r >> 1;
    	build(rt << 1, l, mid);
    	build(rt << 1 | 1, mid + 1, r);
    	lb[rt] = lb[rt << 1].mixed(lb[rt << 1 | 1]);
    }
    
    bool query(int rt, int l, int r, int ql, int qr, int w) {
    	if (l >= ql && r <= qr) {
    		return !lb[rt].canIns(w);
    	}
    	int mid = l + r >> 1;
    	if (ql <= mid && !query(rt << 1, l, mid, ql, qr, w)) return false;
    	if (qr > mid && !query(rt << 1 | 1, mid + 1, r, ql, qr, w)) return false;
     	return true;
    }
    
    int main() {
    	scanf("%d %d", &n, &m);
    	build(1, 1, n);
    	while (m--) {
    		scanf("%d %d %d", &l, &r, &x);
    		if (x == 0) {
    			puts("YES");
    			continue;
    		}
    		if (query(1, 1, n, l, r, x)) puts("YES");
    		else puts("NO");
    	}
    	return 0;
    }
    
  • 相关阅读:
    用户自定义控件
    sql 动态行转列
    sql 将表B中不存在表A的数据 插入到表A中
    C#获取键盘和鼠标操作的时间的类
    滚动条加粗和panel,gridControl结合用
    第三项任务——用例建模
    第二项任务——项目需求分析
    第一项任务:团队组建及项目启动
    实验报告(结对项目)
    实验报告(个人项目)
  • 原文地址:https://www.cnblogs.com/ChaseNo1/p/11750086.html
Copyright © 2011-2022 走看看