BZOJ3261: 最大异或和

【传送门:BZOJ3261


简要题意:

  给出n个数,有m个操作,有两种操作:

  A x在序列末尾添加一个数x,序列长度+1

  Q l r x在l到r中选出一个位置q,使得a[p]^a[p+1]^... ^a[n]^x最大,求出这个最大值


题解:

  可持久化01字典树的例题

  其实建图和查找都和主席树差不多,而找最大值的时候贪心找就可以了


参考代码:

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
struct trie
{
    int son[2],c;
}tr[15000000];int trlen;
int rt[15000000];
void Link(int &u1,int v,int d)
{
    if(u1==0) u1=++trlen;
    tr[u1].c++;
    if(d<0) return ;
    int p=(v>>d)&1;
    Link(tr[u1].son[p],v,d-1);
}
void Merge(int &u1,int u2)
{
    if(u1==0){u1=u2;return ;}
    if(u2==0) return ;
    tr[u1].c+=tr[u2].c;
    Merge(tr[u1].son[0],tr[u2].son[0]);
    Merge(tr[u1].son[1],tr[u2].son[1]);
}
int query(int x,int y,int v,int d)
{
    if(d<0) return 0;
    int p=(v>>d)&1;
    int tmp=tr[tr[x].son[p^1]].c-tr[tr[y].son[p^1]].c; 
    if(tmp>0) return (1<<d)+query(tr[x].son[p^1],tr[y].son[p^1],v,d-1);
    else return query(tr[x].son[p],tr[y].son[p],v,d-1);
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);n++;
    trlen=0;
    Link(rt[1],0,24);
    int tot=0;
    for(int i=2;i<=n;i++)
    {
        int d;
        scanf("%d",&d);tot^=d;
        Link(rt[i],tot,24);
        Merge(rt[i],rt[i-1]);
    }
    char st[5];
    while(m--)
    {
        scanf("%s",st+1);
        if(st[1]=='A')
        {
            int d;
            scanf("%d",&d);tot^=d;
            n++;
            Link(rt[n],tot,24);
            Merge(rt[n],rt[n-1]);
        }
        else
        {
            int x,y,k;
            scanf("%d%d%d",&x,&y,&k);
            printf("%d\n",query(rt[y],rt[x-1],tot^k,24));
        }
    }
    return 0;
}

 

猜你喜欢

转载自www.cnblogs.com/Never-mind/p/8849547.html