The meaning of problems
Given a length \ (N \) sequence \ (A \) , request all the following conditions triples \ (<x, y, z > \)
- \(1\leq x < y < z \leq N\)
- \(a_x \oplus a_y < a_y \oplus a_z\)
Here \ (\ Oplus \) computing a bitwise XOR means
solution
XOR \ (+ \) sequence problem \ (\ to \) 01Trie
It is natural to think enumeration \ (Y \) , for \ (1 \ to y-1 \) and \ (y + 1 \ to N \) respectively maintains a Trie, calculated qualified \ (<x, z > \) number tuple
We can see that if the bit considered, comparing \ (the X-, \) \ (z \) and (y \) \ XOR value of the size, in fact, play a decisive role \ (x, z \) of the first bit to low bit different
Trie violence on the complexity of DFS is clearly wrong, it may reach the level of the index
Due to the dynamic additions and deletions to maintain a chain Trie a time, consider the impact of statistical brought this chain
Set \ (f [i] [0/1 ] \) is considered from high to low, the former \ (i-1 \) the same position, the \ (I \) bit different \ (<x, z> \ ) logarithm. Wherein the second dimension is \ (0 \) Representative \ (X \) of \ (I \) bit \ (0 \) , \ (Z \) of \ (I \) bit \ (1 \ ) (so our Trie is established by the high to low)
We just need to maintain this dynamic in Trie \ (f \) directly with an array, statistical answer \ (f \) array can be updated
Code
#include <cstdio>
#include <cctype>
#include <cstring>
using namespace std;
const int MAX_N = 1e5 + 10;
const int lg = 30;
int read();
int a[MAX_N];
long long ans;
long long f[lg + 1][2];
struct Trie {
int root, cnt;
struct node {
int sum;
int ch[2];
} t[MAX_N * lg];
void clear() {
for (int i = 1; i <= cnt; ++i)
t[i].ch[0] = t[i].ch[1] = t[i].sum = 0;
cnt = root = 1;
}
void ins(int x) {
int p = root;
for (int i = lg; i >= 0; --i) {
int c = x >> i & 1;
if (!t[p].ch[c])
t[p].ch[c] = ++cnt;
p = t[p].ch[c];
t[p].sum++;
}
}
void era(int x) {
int p = root;
for (int i = lg; i >= 0; --i) {
int c = x >> i & 1;
p = t[p].ch[c];
t[p].sum--;
}
}
} tr_a, tr_b;
// f[x][0] : pre 0 suf 1
// f[x][1] : pre 1 suf 0
void add(int x) {
int p = 1;
for (int i = lg; i >= 0; --i) {
int c = x >> i & 1;
f[i][c] += tr_b.t[tr_b.t[p].ch[c ^ 1]].sum;
p = tr_b.t[p].ch[c];
}
}
void del(int x) {
int p = 1;
for (int i = lg; i >= 0; --i) {
int c = x >> i & 1;
f[i][c ^ 1] -= tr_a.t[tr_a.t[p].ch[c ^ 1]].sum;
p = tr_a.t[p].ch[c];
}
}
int main() {
// freopen("xyz.in", "r", stdin);
// freopen("xyz.out", "w", stdout);
int T = read();
while (T--) {
int N = read();
for (int i = 1; i <= N; ++i) a[i] = read();
ans = 0;
tr_a.clear(), tr_b.clear();
memset(f, 0, sizeof f);
for (int i = 2; i <= N; ++i) tr_b.ins(a[i]);
for (int i = 2; i < N; ++i) {
del(a[i]), tr_b.era(a[i]);
add(a[i - 1]), tr_a.ins(a[i - 1]);
for (int j = lg; j >= 0; --j)
ans += f[j][a[i] >> j & 1];
}
printf("%lld\n", ans);
}
return 0;
}
int read() {
int x = 0, c = getchar();
while (!isdigit(c)) c = getchar();
while (isdigit(c)) x = x * 10 + c - 48, c = getchar();
return x;
}