BZOJ3261: 最大异或和

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3261

a[i]^...^a[j]=(a[1]^...^a[j])^(a[1]^...^a[i-1]) 。

然后建立可持久化trie搞就可以了。

#include<cstring>
#include<iostream>
#include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r;i--)
#define clr(x,y) memset(x,y,sizeof(x))
#define maxn 600500
#define inf int(1e9)
#define ull unsigned long long
#define seed 419
#define mm 1000000007
using namespace std;
int s[maxn*30][2],bin[22],sum[maxn*30],root[maxn],n,m,cnt;
int a[maxn],b[maxn];
char ch[2];
int read(){
    int x=0,f=1; char ch=getchar();
    while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
void add(int d,int x,int &y,int val){
    y=++cnt;
    sum[y]=sum[x]+1;
    if (d<0) return;
    s[y][0]=s[x][0]; s[y][1]=s[x][1];
    int p=((val>>d)&1);
    if (p) add(d-1,s[x][1],s[y][1],val);
    else add(d-1,s[x][0],s[y][0],val);
}
int ask(int d,int x,int y,int val){
    if (d<0) return 0;
    int p=((val>>d)&1);
    if (sum[s[y][p^1]]-sum[s[x][p^1]]>0) return (1<<d)+ask(d-1,s[x][p^1],s[y][p^1],val);
    else return ask(d-1,s[x][p],s[y][p],val);
}
int main(){
    n=read(); m=read();
    //bin[0]=1; rep(i,1,20) bin[i]=bin[i-1]*2;
    n++;
    add(24,root[0],root[1],0);
    rep(i,2,n) {
        a[i]=read(); b[i]=b[i-1]^a[i];
        add(24,root[i-1],root[i],b[i]);
    }   
    rep(i,1,m){
        scanf("%s",ch);
        if (ch[0]=='A'){
            n++; a[n]=read(); b[n]=b[n-1]^a[n];
            add(24,root[n-1],root[n],b[n]);
        }
        else {
            int l=read(),r=read(),x=read();
            printf("%d\n",ask(24,root[l-1],root[r],b[n]^x));
        }
    }
    return 0;
}

 

posted on 2015-12-22 21:37  ctlchild  阅读(190)  评论(0编辑  收藏  举报

导航