zoukankan      html  css  js  c++  java
  • 【YbtOJ#20075】区间异或

    题目

    题目链接:http://noip.ybtoj.com.cn/problem/20075

    思路

    先做一遍前缀异或和,然后问题转化为序列中任选两个数异或起来不小于 (k)
    从高位到低位建立 Trie 树,分 (01) 计算答案即可。
    时间复杂度 (O(Tnlog n))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int N=1000010,LG=30;
    int Q,n,m;
    ll ans;
    
    int read()
    {
    	int d=0; char ch=getchar();
    	while (!isdigit(ch)) ch=getchar();
    	while (isdigit(ch)) d=(d<<3)+(d<<1)+ch-48,ch=getchar();
    	return d;
    }
    
    struct Trie
    {
    	int tot,c[N*LG][2],size[N*LG];
    	
    	void ins(int v)
    	{
    		int p=1;
    		for (int i=LG;i>=0;i--)
    		{
    			int id=(v>>i)&1;
    			if (!c[p][id]) c[p][id]=++tot;
    			p=c[p][id];
    			size[p]++;
    		}
    	}
    	
    	int query(int v)
    	{
    		int p=1,sum=0;
    		for (int i=LG;i>=0;i--)
    		{
    			int id=(v>>i)&1,id1=(m>>i)&1;
    			if (!id1) sum+=size[c[p][id^1]];
    			p=c[p][id^id1];
    		}
    		return sum+size[p];
    	}
    	
    	void clr(int p)
    	{
    		if (c[p][0]) clr(c[p][0]);
    		if (c[p][1]) clr(c[p][1]);
    		size[p]=c[p][0]=c[p][1]=0;
    	}
    }trie;
    
    void prework()
    {
    	ans=0; trie.tot=1;
    	trie.clr(1);
    	trie.ins(0);
    }
    
    int main()
    {
    	freopen("xor.in","r",stdin);
    	freopen("xor.out","w",stdout);
    	Q=read();
    	while (Q--)
    	{
    		prework();
    		n=read(); m=read();
    		for (int i=1,x=0;i<=n;i++)
    		{
    			x^=read();
    			ans+=trie.query(x);
    			trie.ins(x);
    		}
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    MySQL5.7初始密码查看及重置
    ps top kill
    Linux基础知识[2]【延迟及定时机制】
    大数加减运算
    字符串分隔
    打印NxN的矩阵
    交叉排序
    去除重复字符并排序
    大数求差——(华为实习招聘机试题)
    图解TCP-IP协议
  • 原文地址:https://www.cnblogs.com/stoorz/p/13914606.html
Copyright © 2011-2022 走看看