最大异或和(可持久化01字典树)

最大异或和

https://ac.nowcoder.com/acm/problem/51120

题目:

给定一个非负整数序列,初始长度为
个操作,有以下两种操作类型:
:添加操作,表示在序列末尾添加一个数,序列的长度
:询问操作,你需要找到一个位置,满足,使得: 最大,输出最大是多少。


做法:

我们直接看查询操作,它是要求序列的某个后缀的和,的最大值。我们设表示序列前个数的和。则其实是要求的最大值。而插入操作只是在末尾多加了一个数罢了,不会影响前面的,处理容易。
由于在每次询问时都确定的,我们设,则现在要解决的问题是:每个询问在区间中找一个,使的值最大。假如没有区间的限制,就是一个字典树。而加了区间限制意味着我们每次询问需要的是只包含一段序列的字典树,所以需要用到可持久化字典树。当我们询问区间时,相当于用第个版本的树-第个版本的树得到区间的树。


代码:

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false), cin.tie(0)
#define debug(a) cout << #a ": " << a << endl
using namespace std;
typedef long long ll;
const int N = 1e6 + 7;
const int M = 2e7 + 7;
int tot, root[N];
int T[M][2], sze[M][2];
void insert(int pre, int &now, int x, int dep){
    if (dep == -1) return;
    now = ++tot;
    int b = (x>>dep)&1;
    T[now][b^1] = T[pre][b^1], sze[now][b^1] = sze[pre][b^1];
    sze[now][b] = sze[pre][b]+1;
    insert(T[pre][b], T[now][b], x, dep-1);
}
int query(int l, int r, int x, int dep){
    if (dep == -1) return 0;
    int b = (x>>dep)&1;
    if (sze[r][b^1]-sze[l][b^1] > 0){
        return query(T[l][b^1], T[r][b^1], x, dep-1)+(1<<dep);
    }else{
        return query(T[l][b], T[r][b], x, dep-1);
    }
}
int main(void){
    IOS;
    int n, m; cin >> n >> m;
    int xorsum = 0;
    for (int i = 1; i <= n; ++i){
        int x; cin >> x; xorsum ^= x;
        insert(root[i-1], root[i], xorsum, 30);
    }
    while (m--){
        string op; cin >> op;
        if (op == "A"){
            int x; cin >> x; xorsum ^= x;
            insert(root[n], root[n+1], xorsum, 30); n++;
        }else{
            int l, r, x; cin >> l >> r >> x;
            x ^= xorsum;
            if (r == 1) cout << x << endl;
            else cout << query(root[max(l-2, 0)], root[r-1], x, 30) << endl;
        }
    }
    return 0;
}
全部评论

相关推荐

大方的大熊猫准备进厂:1.教育背景:你希望从事什么专业的工作你的主修课就是什么;成绩优秀是你应该做的,没什么可描述的,成绩不优秀也许人家在大学忙着创业呢?(成绩优秀不一定是好事,只能说明多元化的大学你上成了高中,没有真正上明白大学,反而体现了你死板,不爱社交,没有别的突出能力) 2.实践经历:你想表达的意思没有说清楚。你是说你会个性化服务,还是你有实习经历。如果没有带来,经济收益,表彰,更好的发展前景,那你还不如说说提升了自己哪些技能。你说有人给你送锦旗我都能明白你优秀,但是你说你会xxxx,你说这话谁信,证据呢。 3.入伍经历:你描述的就是你的工作职责或者你应该做的,并没有体现出来你把这个事情做好了,而且入伍经历并不能证明你能干好你要应聘的工作,不如只写经历其余所有内容都不写。 4.荣誉技能:重点突出一下,但不要过多描述,这些荣誉的含金量懂得都懂。 重点:你要应聘什么工作(具体岗位,实习生不具体),你的期望薪资
点赞 评论 收藏
分享
评论
3
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务