zoukankan      html  css  js  c++  java
  • 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;
    }
    想的太多,做的太少。
  • 相关阅读:
    BZOJ3779: 重组病毒
    BZOJ3112 [ZJOI2013]防守战线
    BZOJ4011 [HNOI2015]落忆枫音
    BZOJ2726 [SDOI2012]任务安排
    BZOJ1492 [NOI2007]货币兑换
    BZOJ1597 [USACO2008]土地购买
    BZOJ3611 [HEOI2014]大工程
    BZOJ3991 [SDOI2015]寻宝游戏
    BZOJ3675 [APIO2014]序列分割
    BZOJ1010 [HNOI2008]玩具装箱
  • 原文地址:https://www.cnblogs.com/pealicx/p/6115595.html
Copyright © 2011-2022 走看看