zoukankan      html  css  js  c++  java
  • 51Nod1577 异或凑数 线性基

    原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1577.html

    题意

      给定一个长度为 n 的序列。

      有 m 组询问,每一组询问给出 L,R,k ,询问 L,R 区间内是否能找出一些数,使它们 XOR 起来等于 k 。

      $n,mleq 5 imes 10^5,  0leq a_i,k< 2^{30}$

    题解

      由于 $n,m$ 同阶,所以以下时间复杂度描述时,对于 $n,m$ 不加区分。

      线性基合并是 $O(log ^2 a_i)$ 的。

      直接线段树维护区间线性基或者 ST 表复杂度均为 $O(nlog ^3 a_i)$ 。

      CDQ分治时间复杂度为 $O(nlog ^2 a_i)$ 。

      以上算法均不能通过。

      考虑将询问离线,按照 R 从小到大排序。

      我们将 $a_i$ 从左到右依次加入。利用线性基维护尽量靠右的基向量即可(经典套路)。

      时间复杂度为 $O(nlog a_i)$ 。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int read(){
    	int x=0;
    	char ch=getchar();
    	while (!isdigit(ch))
    		ch=getchar();
    	while (isdigit(ch))
    		x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    	return x;
    }
    const int N=500005;
    int n,m;
    int a[N];
    struct xxj{
    	int v[30],p[30];
    	void clear(){
    		memset(v,0,sizeof v);
    		memset(p,0,sizeof p);
    	}
    	void insert(int x,int y){
    		for (int i=29;i>=0;i--)
    			if (~x>>i&1)
    				continue;
    			else if (!v[i]){
    				v[i]=x,p[i]=y;
    				break;
    			}
    			else {
    				if (y>p[i])
    					swap(y,p[i]),swap(x,v[i]);
    				x^=v[i];
    			}
    	}
    	int query(int x,int y){
    		for (int i=29;i>=0;i--)
    			if (x>>i&1)
    				if (!v[i]||p[i]<y)
    					return 0;
    				else
    					x^=v[i];
    		return 1;
    	}
    }xianxingji;
    struct Query{
    	int L,R,k,id,ans;
    }q[N];
    bool cmpR(Query a,Query b){
    	return a.R<b.R;
    }
    bool cmpid(Query a,Query b){
    	return a.id<b.id;
    }
    int main(){
    	n=read();
    	for (int i=1;i<=n;i++)
    		a[i]=read();
    	m=read();
    	for (int i=1;i<=m;i++){
    		q[i].L=read();
    		q[i].R=read();
    		q[i].k=read();
    		q[i].id=i;
    	}
    	sort(q+1,q+m+1,cmpR);
    	xianxingji.clear();
    	for (int i=1,j=0;i<=m;i++){
    		while (j<q[i].R)
    			j++,xianxingji.insert(a[j],j);
    		q[i].ans=xianxingji.query(q[i].k,q[i].L);
    	}
    	sort(q+1,q+m+1,cmpid);
    	for (int i=1;i<=m;i++)
    		puts(q[i].ans?"YES":"NO");
    	return 0;
    }
    

      

  • 相关阅读:
    度度熊学队列
    Wannafly挑战赛21
    C. Vasya And The Mushrooms
    D. Vasya And The Matrix
    B. Segment Occurrences
    Codeforces Round #501 (Div. 3)(ABCDE)
    2018 Multi-University Training Contest 4
    1068 : RMQ-ST算法
    Nordic Collegiate Programming Contest 2015​
    Hack It
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/51Nod1577.html
Copyright © 2011-2022 走看看