9.22 xor triplet count

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

Guess you like

Origin www.cnblogs.com/VeniVidiVici/p/11618213.html
XOR