zoukankan      html  css  js  c++  java
  • 【bzoj3261】最大异或和

    题目描述:

    给定一个非负整数序列 {a},初始长度为 N。
    有 M个操作,有以下两种操作类型:

    1 、A x:添加操作,表示在序列末尾添加一个数 x,序列的长度 N+1。
    2 、Q l r x:询问操作,你需要找到一个位置 p,满足 l<=p<=r,使得:

    a[p] xor a[p+1] xor ... xor a[N] xor x 最大,输出最大是多少

    样例输入:

    5 5
    2 6 4 3 6
    A 1
    Q 3 5 4
    A 4
    Q 5 7 0
    Q 3 6 6


    样例输出:

    4
    5
    6

    题解:

    可持久化Trie树,在只有二叉的时候和可持久化线段树非常像。把每个前缀异或和二进制转化后插入可持久化Trie树中,然后询问只要和b[n]^x比较,如果有不同的位就走到不同的位里面去。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
     
    #ifdef WIN32
        #define LL "%I64d"
    #else
        #define LL "%lld"
    #endif
     
    #ifdef CT
        #define debug(...) printf(__VA_ARGS__)
        #define setfile() 
    #else
        #define debug(...)
        #define filename ""
        #define setfile() freopen(filename".in","r",stdin);freopen(filename".out","w",stdout);
    #endif
     
    #define R register
    #define getc() (S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?EOF:*S++)
    #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
    #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
    #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
    #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
    char B[1<<15],*S=B,*T=B;
    inline int FastIn()
    {
        R char ch;R int cnt=0;R bool minus=0;
        while (ch=getc(),(ch < '0' || ch > '9') && ch != '-');
        ch == '-' ?minus=1:cnt=ch-'0';
        while (ch=getc(),ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';
        return minus?-cnt:cnt;
    }
    #define maxn 700010
    #define maxt 15000010
    int trie[maxt][2], b[maxn], sum[maxt], root[maxn], cnt ,p[30];
    inline void Insert (R int last, R int x)
    {
        R int ch = last;
        for (R int i = 24; i>=0 ; i--)
        {
            R int t = x&p[i];
            t >>= i;
            sum[++cnt] = sum[ch] + 1;
            trie[cnt][t] = cnt + 1;
            trie[cnt][t ^ 1] = trie[ch][t ^ 1];
            ch = trie[ch][t] ;
        }
        sum[++cnt] = sum[ch] + 1;
    }
    inline int Query (R int l, R int r, R int x)
    {
        R int ans = 0;
        for (R int i = 24; i>=0 ; i--)
        {
            R int t = x&p[i];
            t >>= i;
            if (sum[trie[r][t^1]] - sum[trie[l][t^1]] > 0)
            {
                ans |= p[i];
                r = trie[r][t^1];
                l = trie[l][t^1];
            }
            else
            {
                r = trie[r][t];
                l = trie[l][t];
            }
        }
        return ans;
    }
    int main()
    {
        //setfile();
        R int n = FastIn(), m = FastIn();
        p[0] = 1;
        for (R int i = 1; i <= 24; i++) p[i] = p[i - 1] << 1;
        b[1] = 0 ;
        root[1] = 1 ;
        Insert(0 , 0);
        n++;
        for (R int i = 2; i <= n; i++)
        {
            R int a = FastIn();
            b[i] = b[i - 1] ^ a;
            root[i] = cnt + 1;
            Insert(root[i - 1], b[i]);
        }
        for (R int i = 1; i <= m; i++)
        {
            R char cmd = getc();
            while (cmd!='A'&&cmd!='Q') cmd = getc();
            if (cmd=='A')
            {
                R int x = FastIn();
                ++n;
                b[n] = b[n - 1] ^ x;
                root[n] = cnt + 1;
                Insert(root[n - 1], b[n]);
            }
            else
            {
                R int l = FastIn(), r = FastIn(), x = FastIn();
                //printf("%d %d %d
    ",l , r ,x );
                printf("%d
    ",Query(root[l - 1], root[r], b[n] ^ x) );
            }
        }
        return 0;
    }



  • 相关阅读:
    如何禁用事件的浮升(div的子元素的点击事件会触发父元素的点击事件)
    如何用Ajax加载服务器的图片
    MyBaits一对一的查询方法
    WEB编程中获取src目录下的文件(没有src目录)
    Vs code背景图
    JS正则表达式
    宏任务和微任务:setTimeout和Promise执行顺序
    MySql操作(一)
    Js 运行机制和Event Loop
    浅拷贝与深拷贝
  • 原文地址:https://www.cnblogs.com/cocottt/p/6765025.html
Copyright © 2011-2022 走看看