HZAU 1206 MathematicalGame

题目链接

Description

     Xiao Ming likes to play mathematical games very much. One day, he gets a sequence of n positive integers. XOR (l , r) is defined as the XOR and of all numbers in a continuous interval. Now, Xiao Ming wants to know the intervals which make the XOR (l , r) become largest.

    Require l, r. 

Input

     There is an integer T at the first line, indicate the case of data.

     In each case, there is an integer N at the first line, indicate the length of the sequence. And there are N integers, a1, a2, … , an, at the second line. (N <= 1,000,000) 

Output

    In each case, the first line is “Case #k:”, k is the number of test cases, the next line includes two integers l and r, which separated by a space.

    l, r output in lexicographic order if there are multiple results.  

Sample Input

1
5
1 2 3 4 5

Sample Output

Case #1:
3 4

求异或和最大的区间,如果有多个区间符合要求要求,输出字典序最小的一种。

异或的性质: 
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]

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int INF=0x3f3f3f3f;

int n,num,ans,l,r,cnt;
int ch[1000003*32][2];//字典树第i层第j个子节点的编号
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 cas=1;cas<=T;cas++)
    {
        scanf("%d",&n);
        printf("Case #%d:\n",cas);
        init();
        Insert(0,0);
        for(int i=1;i<=n;i++)//枚举r
        {
            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;
}

猜你喜欢

转载自blog.csdn.net/jinghui_7/article/details/82905634
今日推荐