初试01字典树(求异或问题)

来源:互联网 发布:淘宝联盟点击赚钱 编辑:程序博客网 时间:2024/05/29 04:33

题目链接

一般01字典树用来解决区间异或和之类的问题。
异或的性质:
1. 交换律
2. 结合律,即(a^b)^c = a^(b^c))
3. 自反性,即x^x=0
4. x^0=x
其中运用最多的就是自反性。

有上述性质,对于区间异或和要知道如下性质:
XOR[l,r] = XOR[1,l-1] ^ XOR[1,r]

在查询最大异或值时我们用贪心的策略,比如我们在字典树中查询10101的最大异或值。
我们从最高位即第5位开始查(我省略掉前面的0位),由于第5位是1(对于其它的任意数,我们设为idx),之后看字典树中有没有第5为是1^1(idx^1)的数,如果有就进入0(idx^1)的节点(贪心思想,即首先保证该位异或后值为1,使异或值尽可能大),没有就进入1(idx)节点,然后从高位到低位依次这样即可。

题意:求n个数中最大异或和值的区间。有多个答案区间按字典序输出。

题解:把1-n的所有前缀异或和插入01字典树,然后按区间异或的性质扫一遍就可以了。复杂度(n*32(字典树深度))

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#include<iostream>#include<algorithm>#include<stack>#include<queue>#include<vector>#include<set>#include<map>#include<string>using namespace std;typedef long long ll;typedef pair<int,int>P;const int INF=0x3f3f3f3f;int n,num,ans,l,r,cnt;int ch[1000003*32][2];int idx[1000003*32];//记录字典序void init(){    num=0;cnt=1;ans=l=r=0;    memset(idx,INF,sizeof(idx));    memset(ch[0],0,sizeof(ch[0]));}void Insert(int id,int x){    int k=0;    for(int i=31;i>=0;i--)    {        int tmp=(x>>i)&1;        if(!ch[k][tmp])        {            memset(ch[cnt],0,sizeof(ch[cnt]));ch[k][tmp]=cnt++;        }        k=ch[k][tmp];    }    if(id<idx[k])idx[k]=id;//保证同一个异或和的字典序最小。每一个k值代表一个异或和}void query(int id,int x){    int k=0,res=0;    for(int i=31;i>=0;i--)    {        int tmp=(x>>i)&1;//贪心策略,从高位开始,让高位尽可能的为1,那么这个数位如果是1,那么就找0(1^1),如果是0,那么就找1(0^1);        if(ch[k][tmp^1]){k=ch[k][tmp^1];res+=(1<<i);}        else{k=ch[k][tmp];res+=(0<<i);}//如果并没有,那么往下贪心,这一位不变    }    if(res>ans){ans=res;l=idx[k];r=id;}    else if(res==ans)    {        if(idx[k]<l){l=idx[k];r=id;}        else if(idx[k]==l&&id<r){r=id;}    }}int main(){    int t,x;scanf("%d",&t);    for(int ca=1;ca<=t;ca++)    {        scanf("%d",&n);printf("Case #%d:\n",ca);        init();Insert(0,0);        for(int i=1;i<=n;i++)        {            scanf("%d",&x);num^=x;            Insert(i,num);query(i,num);        }        printf("%d %d\n",l+1,r);//因为XOR[l,r] = XOR[1,l-1] ^ XOR[1,r],所以l需要+1    }    return 0;}




原创粉丝点击