蓝桥杯真题 - 异或和之差 - 题解

题目链接:https://www.lanqiao.cn/problems/3524/learning/

个人评价:难度 3 星(满星:5)

前置知识:前缀和,字典树


整体思路

  • 定义 l m a x i lmaxi lmaxi 为所有右端点小于等于 i i i 的区间异或和的最大值, r m a x i rmaxi rmaxi 为所有左端点大于等于 i i i 的区间异或和最大值,同理定义 l m i n i lmini lmini 与 r m i n i rmini rmini,则答案如下:

a n s = max ⁡ ( l m a x i − r m i n i + 1 , r m a x i + 1 − l m i n i ) i ∈ 2 , n ans=\max(lmaxi - rmini + 1, rmaxi + 1 - lmini) \quad i\in2, n ans=max(lmaxi−rmini+1,rmaxi+1−lmini)i∈2,n

  • 考虑 l m a x lmax lmax 数组的维护( l m i n , r m i n , r m a x lmin, rmin, rmax lmin,rmin,rmax 数组同理),在枚举到第 i i i 个数字时,如果能快速找到以 i i i 为右端点的所有区间异或和最大值,再将这个最大值与 l m a x i − 1 lmaxi - 1 lmaxi−1 取 m a x max max,就是 l m a x i lmaxi lmaxi 的值;
  • 定义 s u m i sumi sumi 为前 i i i 个数字的前缀异或和,将 s u m i sumi sumi 与所有 s u m j ( j ∈ 0 , i ) ) sum\[j~(j \in 0, i)) sum\[j (j∈0,i)) 异或和的最大值即第二点所求值,将所有 s u m \[ j sumj sumj 放入 01 01 01 字典树中,即可 O ( log ⁡ n ) O(\log n) O(logn) 时间复杂度求出该最大值。

过题代码

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int maxn = 200000 + 100;
const int maxcnt = 200000 * 21 + 100;
const int Size = 2;

// 01 Trie 模板代码
struct Trie {
    int root, cnt;
    int tree[maxcnt][Size];

    int create() {
        ++cnt;
        memset(tree[cnt], 0, sizeof(tree[cnt]));
        return cnt;
    }

    void Init() {
        cnt = 0;
        root = create();
    }

    void add(int x) {
        int pos = root;
        for(int i = 20; i >= 0; --i) {
            int w = ((x >> i) & 1);
            if(tree[pos][w] == 0) {
                tree[pos][w] = create();
            }
            pos = tree[pos][w];
        }
    }

    // 从字典树中找到与 x 异或的最大值的结果
    int queryMax(int x) {
        int pos = root;
        int ret = 0;
        for(int i = 20; i >= 0; --i) {
            int w = ((x >> i) & 1);
            if(tree[pos][w ^ 1] == 0) {
                pos = tree[pos][w];
            } else {
                pos = tree[pos][w ^ 1];
                ret ^= (1 << i);
            }
        }
        return ret;
    }

    // 从字典树中找到与 x 异或的最小值的结果
    int queryMin(int x) {
        int pos = root;
        int ret = 0;
        for(int i = 20; i >= 0; --i) {
            int w = ((x >> i) & 1);
            if(tree[pos][w] == 0) {
                pos = tree[pos][w ^ 1];
                ret ^= (1 << i);
            } else {
                pos = tree[pos][w];
            }
        }
        return ret;
    }
} trie;

int n, ans, sum;
int num[maxn];
int lmax[maxn], rmax[maxn], lmin[maxn], rmin[maxn];

int main() {
#ifdef ExRoc
    freopen("test.txt", "r", stdin);
#endif // ExRoc
    ios::sync_with_stdio(false);

    cin >> n;

    trie.Init();
    // 前缀和必须将第 0 位放入
    sum = 0;
    trie.add(sum);
    for (int i = 1; i <= n; ++i) {
        cin >> num[i];
        sum ^= num[i];
        lmax[i] = trie.queryMax(sum);
        lmin[i] = trie.queryMin(sum);
        trie.add(sum);
    }

    trie.Init();
    sum = 0;
    trie.add(sum);
    for (int i = n; i >= 1; --i) {
        sum ^= num[i];
        rmax[i] = trie.queryMax(sum);
        rmin[i] = trie.queryMin(sum);
        trie.add(sum);
    }

    // 最后做一遍前缀 / 后缀 max / min
    for (int i = 2; i <= n; ++i) {
        lmax[i] = max(lmax[i], lmax[i - 1]);
        lmin[i] = min(lmin[i], lmin[i - 1]);
        rmax[n - i + 1] = max(rmax[n - i + 1], rmax[n - i + 2]);
        rmin[n - i + 1] = min(rmin[n - i + 1], rmin[n - i + 2]);
    }

    for (int i = 1; i < n; ++i) {
        ans = max({ans, lmax[i] - rmin[i + 1], rmax[i + 1] - lmin[i]});
    }
    cout << ans << endl;

    return 0;
}
相关推荐
依然鸣5 分钟前
PTA团体程序设计天梯赛L1真题讲解L1-077-080
开发语言·c++·算法·深度优先·pat考试·图论
恣逍信点1 小时前
《凌微经》价值论:变化即本体,价值即涌现
人工智能·科技·程序人生·蓝桥杯·业界资讯·交友·哲学
库玛西2 小时前
现代 C++ 智能指针全景指南:从 RAII 思想到工业级实践
c语言·开发语言·c++·笔记·面试
liulilittle2 小时前
无锁并发容器的设计与实现原理
开发语言·c++·set·map·并发·无锁·lock-free
qeen873 小时前
【数据结构】自平衡二叉搜索树各种旋转算法原理解析及AVL树的C++实现
数据结构·c++·算法
lucas_AI3 小时前
1.2B 小模型赢过 235B 大模型:NaviDC-OCR 把文档解析卷明白了
人工智能·深度学习·算法
Augustzero3 小时前
为什么线程不能说睡就睡?看懂等待与唤醒机制
c++·后端
程序员与背包客_CoderZ3 小时前
Linux D-Bus通信协议详解:从入门到C/C++编码实战
linux·服务器·c语言·c++·嵌入式硬件·嵌入式软件·dbus
冻柠檬飞冰走茶4 小时前
PTA基础编程题目集 7-35有理数均值(C++语言实现)
开发语言·数据结构·c++·算法·均值算法
wangchen_04 小时前
C++正则表达式
开发语言·c++·正则表达式