2018.08.04 bzoj3261: 最大异或和

传送门
简单可持久化01trie树。
实际上这东西跟可持久化线段树貌似是一个东西啊。
要维护题目给出的信息,就需要维护前缀异或和并且把它们插入一棵01trie树,然后利用贪心的思想在上面递归就行了,因为01trie树的深度是 l o g ( m a x ( a [ i ] ) ) 的,因此单次查询的效率就是 l o g ( m a x ( a [ i ] ) ) 的,因此总时间复杂度是 O ( m l o g ( m a x ( a [ i ] ) ) ) 的。
代码:

#include<bits/stdc++.h>
#define N 300005
using namespace std;
int sum[600005],rt[300005*100],n,m,tot=0,cnt=0;
struct Node{int l,r,cnt;}T[300005*100];
inline int read(){
    int ans=0;
    char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
    return ans;
}
int ans=0;
inline void update(int&p,int las,int v,int dep){
    T[p=++tot]=T[las],++T[p].cnt;
    if(dep==-1)return;
    int op=(v>>dep)&1;
    if(!op)update(T[p].l,T[las].l,v,dep-1);
    else update(T[p].r,T[las].r,v,dep-1);
}
inline void query(int ql,int qr,int v,int dep){
    if(dep==-1)return;
    int op=(v>>dep)&1;
    op^=1;
    if(!op){
        if(T[T[qr].l].cnt-T[T[ql].l].cnt)ans+=(1<<dep),query(T[ql].l,T[qr].l,v,dep-1);
        else query(T[ql].r,T[qr].r,v,dep-1);
    }
    else{
        if(T[T[qr].r].cnt-T[T[ql].r].cnt)ans+=(1<<dep),query(T[ql].r,T[qr].r,v,dep-1);
        else query(T[ql].l,T[qr].l,v,dep-1);
    }
}
int main(){
    n=read()+1,m=read(),rt[0]=0,T[0].l=T[0].r=T[0].cnt=0;
    for(int i=2;i<=n;++i)sum[i]=sum[i-1]^read();
    for(int i=1;i<=n;++i)update(rt[i],rt[i-1],sum[i],25);
    while(m--){
        char s[5];
        scanf("%s",s);
        if(s[0]=='A')++n,sum[n]=sum[n-1]^read(),update(rt[n],rt[n-1],sum[n],25);
        else{
            int l=read(),r=read(),x=read()^sum[n];
            ans=0;
            query(rt[l-1],rt[r],x,25);
            cout<<ans<<'\n';
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/dreaming__ldx/article/details/81389101