usaco training 6.1 XOR of cows (dictionary tree)

Topic

Insert picture description here

Input sample

5
1
0
5
4
2

Sample output

6 4 5

Insert picture description here

answer

  1. Finding the largest interval exclusive OR is a variant of the 01 dictionary tree. Our board point here is to find the largest exclusive OR of two numbers. This question is to find the exclusive OR sum of an interval, then we can use the prefix sum Think to do
  2. Use the s array to represent the exclusive OR of the previous i numbers, s[l-1]^s[r] = al ^ al+1 ^ al+2 ^… ^ar, so you can find the exclusive OR of any continuous interval Up
  3. The condition is to satisfy the maximum XOR of the interval and make r as small as possible, then we traverse from left to right, and each time the right end point is increased by one bit (that is, the interval length + 1), to see the maximum XOR in this interval How much, update the answer if it is greater than (equal to not update, because we must ensure that r is as small as possible)
  4. Another condition is: if there are still multiple alternative sequences, then the one with the shortest length is selected. The meaning is to make l as large as possible, we only need to overwrite the same value before with the latter value when inserting, so that each output must be the latter value.
  5. Haven't understood yet? For example, suppose s[3] =5 ,s[5]=5 ,s[7]=9, assuming that the first two conditions are met, the requirements in the question must be s[7] ^ s[5 ], Then how do we avoid s[3], that is, when inserting, we will record the subscript of each point. For the number 5, the number of insertions in the dictionary tree must be twice, in order from front to back, first Insert 5 once, record the subscript as 3, insert 5 for the second time, and find that it already exists, then there is no need to open a new node, just change the subscript of the node 5 to 5

Code

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>

using namespace std;
const int N = 1e5 + 10;
const int M = N * 21;
int n, x;
int s[N], id[M];
int tr[M][2], idx;

void insert(int x, int k) {
    
    
    int p = 0;
    for (int i = 20; i >= 0; i--) {
    
    
        int u = x >> i & 1;
        if (!tr[p][u]) tr[p][u] = ++idx;
        p = tr[p][u];
    }
    id[p] = k;  //记录下标,覆盖操作
}

int query(int x) {
    
    
    int p = 0;
    for (int i = 20; i >= 0; i--) {
    
    
        int u = x >> i & 1;
        if (tr[p][u ^ 1]) p = tr[p][u ^ 1];
        else p = tr[p][u];
    }
    return id[p];
}

int main() {
    
    

    cin >> n;
    insert(s[0], 0);
    int res = -1;
    int l, r;
    for (int i = 1; i <= n; i++) {
    
    
        cin >> x;
        s[i] = s[i - 1] ^ x;
        int k = query(s[i]);
        int maxn = s[i] ^s[k];
        if (maxn > res) {
    
    
            res = maxn;
            l = k + 1, r = i;
        }
        insert(s[i], i);
    }
    cout << res << " " << l << " " << r << endl;
    return 0;
}

Guess you like

Origin blog.csdn.net/qq_44791484/article/details/113815094