您的位置:首页 > 其它

【分治&搜索】hihocoder1509 异或排序

2018-01-16 15:18 423 查看

题目描述:

给定一个长度为 n 的非负整数序列 a[1..n]

你需要求有多少个非负整数 S 满足以下两个条件:

(1).0≤S<260

(2).对于所有1≤i<n,有(a[i] xor S)≤(a[i+1] xor S)

分析:

有了上一题的经验:hihocoder1526 序列的值

现在我们仍然从高到低依次考虑每一位,

1、若满足前i个数中,这一位均为0,后面所有数中,这一位均为1,那么S中的这一位必然为0

2、相反,若满足前i个数中,这一位均为1,后面所有数这一位均为0,那么S中这一位必然为1
4000

在这两种情况下,后面这部分数与前面的数在之后的讨论中需要分开讨论(因为已经满足无论如何后部分都会大于前部分)。

排除这两种情况,还剩下两种:

1、当前这一位所有的数为乱序排列(即0与1互相夹杂),那么这一位无论取什么值,都无法使得当前区间在异或后依然有序,即无解。

2、当前这一位所有的数均相同。此时S取0或1均可。

按着这样的规则一直考虑到最小位即可。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define SF scanf
#define PF printf
#define MAXN 60
using namespace std;
int n;
long long a[MAXN],ans,k;
queue<pair<int,int> >q[2];
void solve(int x){
//PF("(%d %lld)",x,k);
if(x<0)
return ;
int now=x%2;
int flag=0;
while(!q[now].empty()){
int l=q[now].front().first;
int r=q[now].front().second;
q[now].pop();
int las=l;
for(int i=l;i<r;i++){
//PF("[%d %d]\n",x,flag);
if((a[i]&(1ll<<x))!=0&&(a[i+1]&(1ll<<x))==0){
if(flag==2){
k=-1;
return ;
}
q[now^1].push(make_pair(las,i));
las=i+1;
flag=1;
}
if((a[i]&(1ll<<x))==0&&(a[i+1]&(1ll<<x))!=0){
if(flag==1){
k=-1;
return ;
}
q[now^1].push(make_pair(las,i));
las=i+1;
flag=2;
}
}
q[now^1].push(make_pair(las,r));
}
if(flag==0)
k++;
solve(x-1);
}
int main(){
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
SF("%d",&n);
for(int i=1;i<=n;i++)
SF("%lld",&a[i]);
q[1].push(make_pair(1,n));
solve(59);
if(k==-1)
ans=0;
else
ans=1ll<<k;
PF("%lld",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: