usaco 교육 6.1 XOR of cows (사전 트리)

이야기

여기에 사진 설명 삽입

입력 샘플

5
1
0
5
4
2

샘플 출력

6 4 5

여기에 사진 설명 삽입

대답

  1. 가장 큰 간격 배타적 OR 찾기는 01 사전 트리의 변형입니다. 여기서 우리의 보드 포인트 는 두 숫자의 가장 큰 배타적 OR을 찾는 것입니다.이 질문은 간격의 배타적 OR 합계를 찾는 것입니다. 그런 다음 접두사 sum을 사용할 수 있습니다. 할 생각
  2. s 배열을 사용하여 이전 i 숫자의 배타적 OR s [l-1] ^ s [r] = al ^ al + 1 ^ al + 2 ^… ^ ar를 사용하면 다음과 같은 배타적 OR을 찾을 수 있습니다. 연속 간격
  3. 조건은 간격의 최대 XOR을 충족하고 r을 가능한 한 작게 만든 다음 왼쪽에서 오른쪽으로 이동하고 오른쪽 끝 점이 1 비트 씩 증가 할 때마다 (즉, 간격 길이 + 1) 다음을 참조하십시오. 이 간격의 최대 XOR 얼마나 크면 대답을 업데이트합니까 (r가 가능한 한 작은 지 확인해야하므로 업데이트하지 않는 것과 같음)
  4. 또 다른 조건은 여러 개의 대체 시퀀스가있는 경우 길이가 가장 짧은 시퀀스가 ​​선택된다는 것입니다. 의미는 l을 가능한 한 크게 만드는 것입니다. 삽입 할 때 이전에 동일한 값을 후자 값으로 덮어 쓰기 만하면 각 출력이 후자의 값이되어야합니다.
  5. 아직 이해하지 못 하셨나요? 예를 들어 s [3] = 5, s [5] = 5, s [7] = 9라고 가정하고 처음 두 조건이 충족된다고 가정하면 질문의 요구 사항은 s [7] ^ s [5] 여야합니다. , 그러면 s [3]을 피하는 방법, 즉 삽입 할 때 각 점의 첨자를 기록합니다. 숫자 5의 경우 사전 트리의 삽입 횟수는 앞에서 뒤로 순서로 두 번이어야합니다. 먼저 5를 한 번 삽입하고 아래 첨자를 3으로 기록하고 두 번째로 5를 삽입하고 이미 존재하는 것을 확인한 다음 새 노드를 열 필요가 없습니다. 노드 5의 아래 첨자를 5로 변경하기 만하면됩니다.

암호

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

추천

출처blog.csdn.net/qq_44791484/article/details/113815094