1. 程式人生 > >codeforces 665E (字典樹)

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;
}