CodeForces 665E Beautiful Subarrays(Trie)

题意:给出一个序列,问有多少个子序列的异或的值大于等于k。

思路:首先预处理出一个异或的前缀值,对于一个位置j,我们的目标是找到所有的I<j,使得s[j]^s[I]>=k

如果一个一个的求异或值,复杂度为O(n^2),现在考虑一位一位的比较

将前缀的异或值的二进制字符串插入到trie树中,结点的权值为以这个前缀开头的字符串数量

记录当前已走过的二进制位的和为sum,当前二进制位为b,对于当前深度I,如果sum+(1<<i)>=k,那么就加上b^1的权值然后继续朝着b子树向下走

否则的话更新sum,然后想b^1这颗子树走

这样做的话复杂度为O(n*31).

#include <bits/stdc++.h>
#define eps 1e-6
#define LL long long
#define pii pair<int, int>
#define pb push_back
#define mp make_pair
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

const int maxnode = 20000000;
const int N = 30;
int n, k;
int s[1000100];
int ch[maxnode][2];
int val[maxnode];
int sz;
void add(int num) {
	int u = 0;
	for (int i = N; i >= 0; i--) {
		int c = (num>>i) & 1;
		if (!ch[u][c]) 
			ch[u][c] = sz++;
		val[ch[u][c]]++;
		u = ch[u][c];
	}
}
int cal(int num) {
	int ans = 0, sum = 0, u = 0;
	for (int i = N; i >= 0; i--) {
		int c = (num>>i) & 1;
		if (sum+(1<<i) >= k) {
			ans += val[ch[u][c^1]];
			//cout << val[ch[u][c^1]] << " " << c << endl;
			u = ch[u][c];
			if (!u) break;
		}
		else {
			sum += 1<<i;
			u = ch[u][c^1];
			if (!u) break;
		}
	}
	//cout << sum << endl;
	return ans;
}
int main()
{
	//freopen("input.txt", "r", stdin);
	scanf("%d%d", &n, &k);
	LL ans = 0;
	sz = 1;
	add(0);
	for (int i = 1; i <= n; i++) {
		int a;
		scanf("%d", &a);
		s[i] = s[i-1] ^ a;
		ans += cal(s[i]);
		add(s[i]); 
		//cout << ans << endl;
	}
	cout << ans;
	return 0;
}
















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值