[bzoj3261]最大异或和(可持久化trie)

题目大意:

给定一个非负整数序列{a},初始长度为N。
有M个操作,有以下两种操作类型:
1、Ax:添加操作,表示在序列末尾添加一个数x,序列的长度N+1。
2、Qlrx:询问操作,你需要找到一个位置p,满足l<=p<=r,使得:
a[p] xor a[p+1] xor ... xor a[N] xor x 最大,输出最大是多少。
解题关键:可持久化trie模板题。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
#define N 600005
int n,m;
int a[N],sum[N],root[N];
struct trie{
    int cnt;
    int ch[N*25][2],num[N*25],bin[30];
    void init(){ bin[0]=1;for(int i=1;i<30;i++)bin[i]=bin[i-1]<<1;}
    int insert(int x,int val){
        int tmp,y;tmp=y=++cnt;
        for(int i=23;i>=0;i--){
            ch[y][0]=ch[x][0];ch[y][1]=ch[x][1];
            num[y]=num[x]+1;
            int t=(val&bin[i])>>i;
            x=ch[x][t];
            ch[y][t]=++cnt;
            y=ch[y][t];
        }
        num[y]=num[x]+1;
        return tmp;
    }
    int query(int l,int r,int val){
        int tmp=0;
        for(int i=23;i>=0;i--){
            int t=(val&bin[i])>>i;
            if(num[ch[r][t^1]]-num[ch[l][t^1]])
                tmp+=bin[i],r=ch[r][t^1],l=ch[l][t^1];
            else r=ch[r][t],l=ch[l][t];
        }
        return tmp;
    }
}trie;

int main(){
    trie.init();
    scanf("%d%d",&n,&m);
    n++;
    for(int i=2;i<=n;i++)scanf("%d",a+i);
    for(int i=1;i<=n;i++)sum[i]=sum[i-1]^a[i];//异或前缀和
    for(int i=1;i<=n;i++)root[i]=trie.insert(root[i-1],sum[i]);
    char ch[5];
    int l,r,x;
    while(m--){
        scanf("%s",ch);
        if(ch[0]=='A'){
            n++;
            scanf("%d",&a[n]);sum[n]=sum[n-1]^a[n];
            root[n]=trie.insert(root[n-1],sum[n]);
        }
        else{
            scanf("%d%d%d",&l,&r,&x);
            printf("%d\n",trie.query(root[l-1],root[r],sum[n]^x));
        }
    }
    return 0;
}

 

posted @ 2019-02-17 21:10  Elpsywk  阅读(132)  评论(0编辑  收藏  举报