Trie/Xor

题目链接

/*有一个数组a1,a2,a3……an。找到一个连续子段[l,r],使得al ^ al+1 ^……^ ar达到最大。
一般思路:维护前缀异或+暴力;
for(int i=1;i<=n;i++)
    a[i]^=a[i-1];
for(int i=1;i<=n;i++)
    for(int j=1;j<i;i++)
        ans=max(ans,a[i]^a[j]);
数据量很大,暴力不行。
维护前缀异或+Trie优化;
*/
//指针版本
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1000000+5;
const int si=23;
int a[maxn];
int n;
struct node
{
    node *chi[2];
    void init()
    {
        chi[0]=NULL;
        chi[1]=NULL;
    }
};
void Insert(int k,node * root)
{
    for(int i=si;i>=0;i--)
    {
        if((k&(1<<i)))
        {
            if(root->chi[1]==NULL)
            {
                node *t=(node *)malloc(sizeof(node));
                t->init();
                root->chi[1]=t;
            }
            root=root->chi[1];
        }
        else
        {
            if(root->chi[0]==NULL)
            {
                node *t=(node *)malloc(sizeof(node));
                t->init();
                root->chi[0]=t;
            }
            root=root->chi[0];
        }
    }
}
int query(int k,node *root)
{
    int ret=0;
    for(int i=si;i>=0;i--)
    {
        if(k&(1<<i))//找0
        {
            if(root->chi[0]!=NULL)
            {
                root=root->chi[0];
            }
            else
            {
                root=root->chi[1];
                ret+=(1<<i);
            }
        }
        else//找1
        {
            if(root->chi[1]!=NULL)
            {
                root=root->chi[1];
                ret+=(1<<i);
            }
            else
            {
                root=root->chi[0];
            }
        }
    }
    return k^ret;
}
void rease(node * root)
{
    if(root->chi[0]!=NULL)
        rease(root->chi[0]);
    if(root->chi[1]!=NULL)
        rease(root->chi[1]);
    delete root;
}
int main ()
{
    while(~scanf("%d",&n))
    {
        node *root=(node *)malloc(sizeof(node));
        root->init();
        Insert(0,root);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            a[i]^=a[i-1];
            Insert(a[i], root);
        }
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            ans=max(ans,query(a[i], root));
        }
        printf("%d
",ans);
        rease(root);
    }
    return 0;
}
//数组版本
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1000000+5;
const int si=23;
int a[maxn];
int tree[maxn*3][2];
int cnt=0;
int n;
void Insert(int k)
{
    int root=0;
    for(int i=si;i>=0;i--)
    {
        if((k&(1<<i)))
        {
            if(tree[root][1]==0)
            {
                cnt++;
                tree[root][1]=cnt;
            }
            root=tree[root][1];
        }
        else
        {
            if(tree[root][0]==0)
            {
                cnt++;
                tree[root][0]=cnt;
            }
            root=tree[root][0];
        }
    }
}
int query(int k)
{
    int root=0;
    int ret=0;
    for(int i=si;i>=0;i--)
    {
        if(k&(1<<i))//找0
        {
            if(tree[root][0]!=0)
            {
                root=tree[root][0];
            }
            else
            {
                root=tree[root][1];
                ret+=(1<<i);
            }
        }
        else//找1
        {
            if(tree[root][1]!=0)
            {
                root=tree[root][1];
                ret+=(1<<i);
            }
            else
            {
                root=tree[root][0];
            }
        }
    }
    return k^ret;
}
int main ()
{
    while(~scanf("%d",&n))
    {
        memset(tree,0,sizeof(tree));
        cnt=0;
        Insert(0);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            a[i]^=a[i-1];
            Insert(a[i]);
        }
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            ans=max(ans,query(a[i]));
        }
        printf("%d
",ans);
    }
    return 0;
}
想的太多,做的太少。
原文地址:https://www.cnblogs.com/pealicx/p/6115595.html