奶牛异或

来源:互联网 发布:linux ping命令 编辑:程序博客网 时间:2024/05/29 16:11

奶牛异或
时间限制: 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; } 
原创粉丝点击