#10051 Nikitosh 和异或

时间:2020-04-10
本文章向大家介绍#10051 Nikitosh 和异或,主要包括#10051 Nikitosh 和异或使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

Nikitosh 和异或

其实题意已经简单的不能再简单了,所以就不讲了。

因为题目中 \(1\leq l_1 \leq r_1 <l_2 \leq r_2\leq N\),所以显然对于最终答案,总有一个 \(x\) 满足 \(r_1\leq x<l_2\)

那么就可以不断尝试以那个点为 \(x\),来求出答案,具体方法如下:

\(l_i=max_{1\leq l \leq r\leq i}\{a_l\bigoplus a_{l+1}\bigoplus..\bigoplus a_r\}\)\(r_i=max_{i\leq l\leq r\leq N}\{a_l\bigoplus a_{l+1}\bigoplus..\bigoplus a_r\}\)

那么 \(ans=max_{1\leq i<N}\{l_i+r_{i+1}\}\),而关键在于怎么求 \(l_i,r_i\)

这里引入一个概念:异或前缀和,即 \(S_i=a_0\bigoplus a_1\bigoplus a_2\bigoplus...\bigoplus a_i\)。(其中 \(a_0=0\)

那么 \(l_i=max_{1\leq j< i}\{S_i\bigoplus S_j\}\)\(r_i=max_{i< j\leq N}\{S'_i\bigoplus S'_j\}\)。(其中 \(S'_i=a_N\bigoplus a_{N-1}\bigoplus...\bigoplus a_i\)

然后就是简单的 trie 贪心求最大异或对了,但是还有几处细节要注意,都写在代码里了。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <iostream>
#define N 9000010
using namespace std;

int n, trie[N][2], l[N], r[N], a[N], tot = 0;

int read() {
    int x = 0, f = 1;
    char c = getchar();
    while (c < '0' || c > '9') f = (c == '-') ? -1 : 1, c = getchar();
    while (c >= '0' && c <= '9') x = x * 10 + c - 48, c = getchar();
    return x * f;
}

void insert(int x) {
    int p = 0;
    for (int i = 31; i >= 0; i--) {
        int ch = (x >> i) & 1;
        if (!trie[p][ch])
            trie[p][ch] = ++tot;
        p = trie[p][ch];
    }
    return;
}//简单的模板式的插入。

int search(int x) {
    int p = 0, ans = 0;
    for (int i = 31; i >= 0; i--) {
        int ch = (x >> i) & 1;
        if (trie[p][ch ^ 1]) {
            ans |= (1 << i);
            p = trie[p][ch ^ 1];
        } else
            p = trie[p][ch];
    }
    return ans;
}
//简单的模板式的查询。
int main() {
    n = read();
    int s = 0;
    insert(s);
    for (int i = 1; i <= n; i++) {
        a[i] = read();
        s ^= a[i];//当前的异或前缀和。
        insert(s);
        l[i] = max(l[i - 1], search(s));//一定要取 max。
    }
    memset(trie, 0, sizeof(trie));
    tot = 0;//记得清零。
    insert(s);
    for (int i = n; i >= 1; i--) {
        s ^= a[i];
        insert(s);
        r[i] = max(r[i + 1], search(s));//同上。
    }
    int ans = 0;
    for (int i = 1; i < n; i++) ans = max(ans, l[i] + r[i + 1]);
    printf("%d\n", ans);
    return 0;
}

原文地址:https://www.cnblogs.com/lpf-666/p/12674508.html