zoukankan      html  css  js  c++  java
  • [BZOJ 3261]最大异或和

    Description

    题库链接

    给定一个初始长度为 (N) 的非负整数序列 ({A}) 。有 (M) 个操作,支持:

    1. (A~x) :添加操作,表示在序列末尾添加一个数 (x) ,序列的长度 (N+1)
    2. (Q~l~r~x) :询问操作,求 [max_{lleq pleq r}A_poplus A_{p+1}opluscdotsoplus A_Noplus x]

    (1leq N,Mleq 300000,0leq A_ileq 10^7)

    Solution

    不妨记 (A_i) 的前缀异或和为 (B_i) ,显然题目转化为 [max_{lleq pleq r}B_{p-1}oplus B_Noplus x]

    我们不妨用类似主席树的思路,我们建一棵 (B_i)(Trie) ,并且将它持久化,然后贪心的选择。显然是可行的。

    值得注意的是由于异或的前缀和,并且又因为差分,查询时的区间应该为 ([l-2,r-1]) ,为了防止越界,可以先插入个 (0)(Trie)

    Code

    //It is made by Awson on 2018.3.16
    #include <bits/stdc++.h>
    #define LL long long
    #define dob complex<double>
    #define Abs(a) ((a) < 0 ? (-(a)) : (a))
    #define Max(a, b) ((a) > (b) ? (a) : (b))
    #define Min(a, b) ((a) < (b) ? (a) : (b))
    #define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
    #define writeln(x) (write(x), putchar('
    '))
    #define lowbit(x) ((x)&(-(x)))
    using namespace std;
    const int N = 300000;
    void read(int &x) {
        char ch; bool flag = 0;
        for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
        for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
        x *= 1-2*flag;
    }
    void print(int x) {if (x > 9) print(x/10); putchar(x%10+48); }
    void write(int x) {if (x < 0) putchar('-'); print(Abs(x)); }
    
    int n, m, bin[30], a, b, t, A[30], l, r; char ch[5];
    struct Trie {
        int root[(N<<1)+5], ch[N*50+5][2], key[N*50+5], pos;
        int cpynode(int o) {++pos; ch[pos][0] = ch[o][0], ch[pos][1] = ch[o][1], key[pos] = key[o]; return pos; }
        void insert(int &o, int *A) {
        int u = o = cpynode(o); ++key[u];
        for (int i = 25; i >= 1; i--) {
            ch[u][A[i]] = cpynode(ch[u][A[i]]);
            u = ch[u][A[i]], ++key[u];
        }
        }
        int query(int a, int b, int *A) {
        int ans = 0;
        for (int i = 25; i >= 1; i--) {
            if (key[ch[b][A[i]^1]]-key[ch[a][A[i]^1]] > 0) ans += bin[i-1], a = ch[a][A[i]^1], b = ch[b][A[i]^1];
            else a = ch[a][A[i]], b = ch[b][A[i]];
        }
        return ans;
        }
    }T;
    
    void work() {
        read(n), read(m); bin[0] = 1; for (int i = 1; i <= 25; i++) bin[i] = (bin[i-1]<<1);
        T.insert(T.root[1], A); ++n;
        for (int i = 2; i <= n; i++) {
        read(a), b ^= a, t = b; for (int j = 1; j <= 25; j++) A[j] = t%2, t /= 2;
        T.insert(T.root[i] = T.root[i-1], A);
        }
        while (m--) {
        scanf("%s", ch);
        if (ch[0] == 'A') {
            ++n; read(a), b ^= a, t = b;
            for (int j = 1; j <= 25; j++) A[j] = t%2, t /= 2;
            T.insert(T.root[n] = T.root[n-1], A);
        }else {
            read(l), read(r), read(t); t ^= b;
            for (int j = 1; j <= 25; j++) A[j] = t%2, t /= 2;
            writeln(T.query(T.root[l-1], T.root[r], A));
        }
        }
    }
    int main() {
        work(); return 0;
    }
  • 相关阅读:
    RIGHT-BICEP单元测试——“二柱子四则运算升级版”
    个人项目之“二柱子四则运算升级版”(续)
    个人项目之 “二柱子四则运算”升级版
    “进度条”博客
    课后实验3--四则运算3
    构建之法阅读笔记01
    第二周学习进度
    四则运算2单元测试
    课后实验2--四则运算2
    课后实验1--四则运算
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/8578413.html
Copyright © 2011-2022 走看看