joj 2732: Cow XOR 求最大异或段

帮助农夫约翰选择一串连续的奶牛,使它们的分配数字的异或值最大。如果存在多个这样的序列,则选择排名最高的奶牛作为序列的结束。若仍有多个选项,则选择最短的序列。
摘要由CSDN通过智能技术生成

Farmer John is stuck with another problem while feeding his cows. All of his N (1 ≤ N ≤ 100,000) cows (numbered 1..N) are lined up in front of the barn, sorted by their rank in their social hierarchy. Cow #1 has the highest rank; cow #N has the least rank. Every cow had additionally been assigned a non-unique integer number in the range 0..(2^21 - 1).
Help FJ choose which cows will be fed first by selecting a sequence of consecutive cows in the line such that the bitwise "xor" between their assigned numbers has the maximum value. If there are several such sequences, choose the sequence for which its last cow has the highest rank. If there still is a tie, choose the shortest sequence.

Input

MULTI TEST CASE!! For Each Test Case
Line 1: A single integer N
Lines 2..N+1: N integers ranging from 0 to 2^21 - 1, representing the cows' assigned numbers. Line j describes cow of social hierarchy j-1.

Output

Line 1: Three space-separated integers, respectively: the maximum requested value, the position where the sequence begins, the position where the sequence ends.

Sample Input

5
1
0
5
4
2

Sample Output

6 4 5

Hint

4 xor 2 = 6 (001) xor (010) = (011) 

Problem Source: USACO Training

 

 //

 

 

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=3010000;
//找异或值最大的两个数
int n;//0~n-1
int a[maxn];
int l,r;
struct Node
{
    int flag;
    Node* next[2];
};
Node temp[maxn];
int tp;
Node *root;
void reset(Node* p)
{
    p->flag=-1;
    for(int i=0;i<2;i++) p->next[i]=NULL;
}
void init()
{
    tp=0;
    root=&temp[tp++];
    reset(root);
}
void insert(char* word,int id)
{
    Node* p=root;
    for(int i=0;word[i];i++)
    {
        int x=word[i]-'0';
        if(p->next[x]==NULL)
        {
            p->next[x]=&temp[tp++];
            reset(p->next[x]);
        }
        p=p->next[x];
    }
    p->flag=id;
}
int tl;
int solve(int v)
{
    Node* p=root;
    int cnt=0;
    for(int i=30;i>=0;i--)
    {
        int x;
        if(v&(1<<i)) x=1;
        else x=0;
        if(p->next[!x]) p=p->next[!x],cnt|=(1<<i);
        else p=p->next[x];
    }
    tl=p->flag;
    return cnt;
}
char str[100];
int findMaxXor()
{
    init();
//    for(int i=0;i<n;i++)
//    {
//        int k=a[i];
//        for(int j=30;j>=0;j--,k>>=1) str[j]=(k&1)+'0';
//        str[31]='\0';
//        insert(str);
//    }
    int ans=-1;
    for(int i=0;i<n;i++)
    {
        int k=a[i];
        for(int j=30;j>=0;j--,k>>=1) str[j]=(k&1)+'0';
        str[31]='\0';
        if(i==0)
        {
            insert(str,i);
            continue;
        }
        int tmp=solve(a[i]);
        if(tmp>ans)
        {
            ans=tmp,l=tl+1,r=i;
        }//相同输出靠前的
//        else if(tmp==ans)
//        {
//            if(r-l+1>i-tl) l=tl+1,r=i;
//        }
        insert(str,i);
    }
    return ans;
}


int t[maxn];
int main()
{
    while(scanf("%d",&n)==1)
    {
        n++;
        t[0]=a[0]=0;
        for(int i=1;i<n;i++)
        {
            scanf("%d",&t[i]);
            a[i]=a[i-1]^t[i];
        }
        int tmp=findMaxXor();
        printf("%d %d %d\n",tmp,l,r);
    }
    return 0;
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值