codeforces 665E (字典树)

E. Beautiful Subarrays
time limit per test
3 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

One day, ZS the Coder wrote down an array of integers a with elements a1,  a2,  ...,  an.

A subarray of the array a is a sequence al,  al  +  1,  ...,  ar for some integers (l,  r) such that 1  ≤  l  ≤  r  ≤  n. ZS the Coder thinks that a subarray of a is beautiful if the bitwise xor of all the elements in the subarray is at least k.

Help ZS the Coder find the number of beautiful subarrays of a!

Input

The first line contains two integers n and k (1 ≤ n ≤ 106, 1 ≤ k ≤ 109) — the number of elements in the array a and the value of the parameter k.

The second line contains n integers ai (0 ≤ ai ≤ 109) — the elements of the array a.

Output

Print the only integer c — the number of beautiful subarrays of the array a.

Examples
input
3 1
1 2 3
output
5
input
3 2
1 2 3
output
3
input
3 3
1 2 3
output
2


题意:求出一个数组的子串使得这个子串的xor值大于等于k.

先求出每一段前缀和,等价于求多少对前缀的xor大于等于k.把前缀扫一遍,每次用利用

前缀的值和k跑字典树,前缀num和k的某一位上有4种情况,我就懒得找统一的规律了

直接讨论:

1:num和k都是1,往字典树当前节点的next[0]走;

2:num和k都是0,字典树当前节点next[1]子树的size和向next[1]走的结果相加;

3:num是1,k是0,字典树当前节点next[0]子树的size和向next[0]走的结果相加;

4:num是0,k是1,往字典树当前节点的next[1]走;

然后每次统计完把num插进字典树,更新每个节点一下的数字个数.

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
using namespace std;
#define maxn 1111111

int a[maxn];
struct node {
	int next[2];
	int num;
}tree[maxn*33];
int root, cnt;
int n, k;

void build_node (int c) {
	if (!tree[c].next[0])
		tree[c].next[0] = ++cnt, tree[tree[c].next[0]].num = 0;
	if (!tree[c].next[1])
		tree[c].next[1] = ++cnt, tree[tree[c].next[1]].num = 0;
}

int dfs (int u, int bit, int num) {
	build_node (u);
	if (tree[u].num == 0 && u != root)
		return 0;
	if (bit == 0) {
        return tree[u].num;
	}
	int ans = 0;
	int id1 = ((num&bit)>=1);//num当前位
	int id2 = ((k&bit)>=1);  //k当前位
	if (id1 && id2) {
		ans += dfs (tree[u].next[0], bit>>1, num);
	}
	else if (!id1 && !id2) {
		ans += tree[tree[u].next[1]].num + dfs (tree[u].next[0], bit>>1, num);
	}
	else if (id1 && !id2) {
		ans += tree[tree[u].next[0]].num + dfs (tree[u].next[1], bit>>1, num);
	}
	else {
		ans += dfs (tree[u].next[1], bit>>1, num);
	}
	return ans;
}

void insert (int num) {
	int p = root;
	int bit = (1<<30);
	while (bit) {
		tree[p].num++;
		build_node (p);
		int id = ((num&bit)>=1);//当前位
		p = tree[p].next[id];
		bit >>= 1;
	}
	build_node (p);
	tree[p].num++;
}

void solve () {
	long long ans = 0;
	root = 1;
	build_node (root);
	for (int i = 1; i <= n; i++) {
		int p = root;
		if (a[i] >= k)
			ans++;
		int cur = (1<<30);
		int gg = dfs (p, cur, a[i]);
		ans += gg;
		insert (a[i]);
	}
	printf ("%lld\n", ans);
}

int main () {
	cnt = 1;
	cin >> n >> k;
	for (int i = 1; i <= n; i++) {
		scanf ("%d", &a[i]);
		if (i > 1)
			a[i] ^= a[i-1];
	}

	solve ();
	return 0;
}


你可能感兴趣的:(codeforces 665E (字典树))