【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\n",l , r ,x );
            printf("%d\n",Query(root[l - 1], root[r], b[n] ^ x) );
        }
    }
    return 0;
}



 

posted @ 2016-03-16 16:49  cot  阅读(180)  评论(0编辑  收藏  举报