码迷,mamicode.com
首页 > 其他好文 > 详细

【YbtOJ#20075】区间异或

时间:2020-11-13 12:21:17      阅读:6      评论:0      收藏:0      [点我收藏+]

标签:计算   lang   while   ref   mamicode   return   getchar   print   turn   

题目

题目链接:http://noip.ybtoj.com.cn/problem/20075
技术图片

思路

先做一遍前缀异或和,然后问题转化为序列中任选两个数异或起来不小于 \(k\)
从高位到低位建立 Trie 树,分 \(01\) 计算答案即可。
时间复杂度 \(O(Tn\log 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\n",ans);
	}
	return 0;
}

【YbtOJ#20075】区间异或

标签:计算   lang   while   ref   mamicode   return   getchar   print   turn   

原文地址:https://www.cnblogs.com/stoorz/p/13914606.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!