奶牛异或

奶牛异或
时间限制: 2 Sec 内存限制: 64 MB
提交: 265 解决: 41
[提交][状态][讨论版]
题目描述
农民约翰在喂奶牛的时候被另一个问题卡住了。他的所有N(1 <= N <= 100,000)个奶牛在他面前排成一行(按序号1..N的顺序),按照它们的社会等级排序。奶牛#1由最高的社会等级,奶牛#N最低。每个奶牛同时被赋予了一个唯一的数在0..2^21 - 1的范围内。帮助农民约翰找出应该从那一头奶牛开始喂,使得从它开始的某一个连续的自序列上的奶牛的数的异或最大。如果有多个这样的子序列,选择结尾的奶牛社会等级最高的。如果还不唯一,选择最短的。

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

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

样例输入
5
1
0
5
4
2
样例输出
6 4 5
提示
来源

0f[i]1ixyf[y]xorf[x1]

f[i]1i1

01

#include<iostream> 
#include<cstdio> 
using namespace std; 
int tree[9000000]; 
int f[200000]; 
void build(int x,int y,int z,int p){
  //cout<<p<<" "<<z<<endl;
  if (z==-1){ 
    tree[p]=y;
    return; 
  } 
  int yh=z; 
  if ((x&(1<<yh))!=0) build(x,y,yh-1,p+p+1);
  else build(x,y,yh-1,p+p); 
  if (tree[p+p]!=0||tree[p+p+1]!=0)tree[p]=1;
}


int search(int x,int y,int z,int p){ 
  if (z==-1) 
    return tree[p]; 
  int yh=z; 
  if (((x&(1<<yh))!=0&&tree[p+p]>0)||(tree[p+p+1]==0))
    return search(x,y,yh-1,p+p);
  else
  if (((x&(1<<yh))==0&&tree[p+p]>0)||(tree[p+p]==0))
    return search(x,y,yh-1,p+p+1); 
} 


int main(){ 
  int n; 
  scanf("%d",&n); 
  f[0]=0; 
  int ma=0; 
  for (int i=1;i<=n;++i){ 
    int t; 
    scanf("%d",&t); 
    f[i]=f[i-1]^t; 
    int a=0; 
    int j=f[i]; 
    while (j!=0) j/=2,++a; 
    ma=max(ma,a);
    //cout<<f[i]<<endl;
  } 
 // for (int i=1;i<=n;++i) build(f[i],i,ma-1,1); 
  //cout<<tree[7]<<" "<<tree[8]<<" "<<tree[9]<<" "<<tree[10]<<" "<<tree[11]<<endl;
  int ans=-1<<29,numi=0,numj=0;
  for (int i=1;i<=n;++i){ 
    int j=search(f[i],i,ma-1,1)+1; 
    int zhi=f[i]^f[j-1]; 
    if ((zhi>ans)||(zhi==ans&&i<numj)||(zhi==ans&&i==numj&&i-j+1<numj-numi+1)){ 
      ans=zhi; 
      numi=j; 
      numj=i; 
    } 
    build(f[i],i,ma-1,1); 
  } 
  printf("%d %d %d\n",ans,numi,numj); 
  return 0; 
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值