Xor sum HDU - 6955

Posted Jozky86

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Xor sum HDU - 6955相关的知识,希望对你有一定的参考价值。

Xor sum HDU - 6955

题意:

给定一个长度为n的整数序列,求其XOR和不小于k的最短连续子序列。

如果有多个相同长度的连续子序列,则打印具有最小左端点的连续子序列。

如果没有连续的子序列开关XOR总和不小于k,只需打印“-1”。

题解:

有关01串且求异或值相关内容,一般都用01字典树,本题也不例外
本题如何维护字典树呢?
我们先求出所有的前缀异或和[1,P],当前在Q的位置,我们寻找一个离Q最近的一个数,使得Q ^ P>=K。每次查询时,(此时字典树中只插入了Q之前的所有前缀异或和),都会从字典数的高位枚举到低位,如果K的第J位是1,为了保证Q ^ P>=K,Q ^ P的值也必须是1,那么P和Q的第J位就要不同,也就是我们要向Q的第J位相反的方向寻找,即 c = (Q>>j)&1寻找nxt[now][c ^ 1]。
如果K的第J位是0,此时Q^P的第J位可以是0或1,如果是1后面就不用比较了,已经大于K了,所以如果有1,即nxt[now][c ^ 1]存在,我们就记录最大的flag[],然后我们要向net[now][c]的方向寻找。为什么?先讲下flag[]表示的该异或值出现位置的最后的一次位置,也就是flag的值会尽可能靠近Q,这样才会让区间最小。我们在插入时维护flag,使得每个点都有最大的flag,当上面说的nxt[now][c ^ 1],此时K的第J位是0,我们不用再去走1这条路,因为已经比K大了,后面的也一定大于K,所以取最大flag即可,但是如果net[now][c]还是要继续走,因为目前还不知道是否大于等于K
(讲的有些乱,可以看看代码,代码很清晰)

代码:

#include<bits/stdc++.h>
#define debug(a,b) printf("%s = %d\\n",a,b);
typedef long long ll;
using namespace std;
//qdu打铁匠
const ll INF=0x3f3f3f3f;
inline int read(){
   int s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);
   return s*w;
}
const int maxn=1e7;
ll nex[maxn][3], cnt=0;
ll flag[210000000];
ll k;
struct trie
{

    void insert(ll x,ll pos)
    {
        int p =0;
        for(int i=29; i>=0; i--)
        {

            ll c=((x>>i)&1);

            if (!nex[p][c])
            {
                nex[p][c] = ++cnt;
                flag[cnt]=-1;
                nex[cnt][1]=nex[cnt][0]=0;
            } // 如果没有,就添加结点
            p = nex[p][c];
            flag[p]=max(flag[p],pos);
        }
    }
    ll find(ll x)
    {
    	ll ma=-1;
        ll p=0;
        for(int i=29; i>=0; i--)
        {
            ll c=((x>>i)&1);
            ll ok=((k>>i)&1);
            if(ok==0)
            {
                if(nex[p][c^1])
                    ma=max(ma,flag[nex[p][c^1]]);
                p=nex[p][c];
            }
            else
            {

                p=nex[p][c^1];
            }
            if(p==0)
                return ma;
        }
        return max(ma,flag[p]);

    }
} tree;
ll a[1111111];
signed main()
{

    ll t;
    t=read();
    while(t--)
    {
        ll n;
        n=read();
        k=read();

        for(int i=1; i<=n; i++)
        {
            a[i]=read();
            a[i]^=a[i-1];
        }
        for(int i=0; i<=cnt; i++)
        {
            nex[i][0]=0;
            nex[i][1]=0;
            flag[i]=0;
        }
        cnt=0;

        ll ansl=0,ansr=n;
        ll ma;
        for(int i=1; i<=n; i++)
        {
            ma=-1;
            ll x=tree.find(a[i]);
            if(x!=-1)
            {
                ma=max(x,ma);

            }
            if(i-ma<ansr-ansl&&ma>0)
            {
                ansl=ma;
                ansr=i;
            }
            tree.insert(a[i],i);
        }
        if(ansl>0)
        {
            printf("%d %d\\n",ansl+1,ansr);
        }
        else
        {
            printf("-1\\n");
        }

    }
}

以上是关于Xor sum HDU - 6955的主要内容,如果未能解决你的问题,请参考以下文章

HDOJ6955Xor sum(异或前缀和,01字典树)

2021杭州多校6955-xor sum(字典树+异或前缀和)

2021杭州多校6955-xor sum(字典树+异或前缀和)

HDU 4825 Xor Sum

HDU--4825 Xor Sum (字典树)

HDU 4825 Xor Sum(01字典树)题解