奶牛xor--nkoi1873

24 篇文章 0 订阅
16 篇文章 0 订阅

Cow XOR奶牛异或

Time Limit:10000MS  Memory Limit:65536K
Total Submit:106 Accepted:48
Case Time Limit:500MS

Description

农民约翰在喂奶牛的时候被另一个问题卡住了。他的所有N(1 <= N <= 100,000)个奶牛在他面前排成一行(按序号1..N的顺序),按照它们的社会等级排序。奶牛#1有最高的社会等级,奶牛#N最低。每个奶牛同时被指定了一个不唯一的附加值,这个数在0..2^21 - 1的范围内。
帮助农民约翰找出应该从哪一头奶牛开始喂,使得从这头奶牛开始的一个连续的子序列上,奶牛的附加值的异或最大。
如果有多个这样的子序列,选择结尾的奶牛社会等级最高的。如果还不唯一,选择最短的。

Input

第1行:一个单独的整数N。
第2到N + 1行:N个0..2^21 - 1之间的整数,代表每头奶牛的被赋予的数。第j行描述了社会等级j - 1的奶牛。

Output

第 1 行: 3个空格隔开的整数,分别为:最大的异或值,序列的起始位置、终止位置。 时限0.5秒

Sample Input

5
1
0
5
4
2

Sample Output

6 4 5




详情请见代码注释


详细注释版代码:

#include<cstdio>
#include<iostream> 
const int m=20;
int n,a[100005];
int f[200005];//f是前缀或 
struct node{
	int kid[2],num;//trie,两个儿子节点分别表示1,0 
};
int tot=1;node trie[2000005];
void insert(int k)
{
	//添加f[k]的二进制形式,保证每一个数深度一样前面可以补0 
     int t=1,i;
     for(i=m;i>=0;i--){
         int now=(f[k]>>i)%2;
         if(trie[t].kid[now]==0)
             trie[t].kid[now]=++tot;
         t=trie[t].kid[now];
     }
     trie[t].num=k;
}
int find(int k)
{
	//根据题意和xor的性质,要找f[i]^f[j]的最大值 
	//find(k)找到的是和f[k]取xor得到最大值的前缀或的编号
	//要使得两个数的xor尽可能的大,当然尽可能地每一位都不一样,当然高位优先 
    int t=1,i;
    for(i=m;i>=0;i--){
        int now=1-(f[k]>>i)%2;
        if(trie[t].kid[now]!=0)t=trie[t].kid[now];
        else t=trie[t].kid[1-now];
    }
    return trie[t].num;
} 
int main(){
     scanf("%d",&n);
     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
     int ans=a[1],s=1,t=1;
     f[1]=a[1];insert(1);
     for(int i=2;i<=n;i++){
         f[i]=f[i-1]^a[i];
         int p=find(i);//如find函数功能,找到使得xor值最大的f[j] 
         if((f[i]^f[p])>ans){
         	//更新答案 
            ans=f[i]^f[p];
            s=p+1;
            t=i;
         }
         insert(i);
     }
     printf("%d %d %d",ans,s,t);
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值