hiho1509 异或排序

题目链接

题目大意:

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

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

(1).0 ≤ S < 260

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

1 ≤ n ≤ 50

0 ≤ a[i] < 260

-------------------------------------------------------------------------------------

开始看到题感觉无从下手,分析了一下才发现是到水题。

维护一个60位的标记数组,用来表示S的第i位可以放置的数(11为置01都可,01为只可置0,10为只可置1,00为都不能放)。初始状态为11。

开始时n个数在一个组内,要满足条件(2),n个数的最高位必须满足

             1)全部为0或1;这时候该位可以放0或者1。

             2)前几个数最高位为0,后面的数为1.(或者反过来),但不会出现01交替出现的情况;这时候该位只能放0或者1.

对于情况1)仍把改组扔到次高位处理。

对于情况2)可以把该组分成两组扔到次高位处理。

#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cmath>
#include <vector>
#include <string>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>

#define MAX(a,b) ((a)>=(b)?(a):(b))
#define MIN(a,b) ((a)<=(b)?(a):(b))
#define OO 0x0fffffff
using namespace std;
typedef long long LL;
const int N = 66;
int digits[N][N];
void getDigits(int id,LL data){
    for(int i=0;i<60;i++){
        digits[id][i]=(data&1L);
        data>>=1;
    }
}
int choice[N];
int n;
LL data;
struct Node{
   int level;
   int spos,epos;
   int sdigit,scnt;
   Node(int tlevel,int tspos,int tepos){
       level = tlevel;
       spos = tspos;
       epos = tepos;
   }
   Node(){}
   int length(){
       return epos-spos+1;
   }
};
int main(){
    cin>>n;
    for(int i=0;i<n;i++) {
       cin>>data;
       getDigits(i,data);
    }
    for(int i=0;i<60;i++) choice[i] = 3;

    Node head(59,0,n-1);
    queue<Node> q;
    q.push(head);
    while(!q.empty()){
        Node cur = q.front(); q.pop();
        cur.sdigit = digits[cur.spos][cur.level];
        cur.scnt = 1;
        for(int r=cur.spos+1;r<=cur.epos;r++){
            if(digits[r][cur.level]==digits[r-1][cur.level])
                cur.scnt++;
            else break;
        }
        if(cur.scnt==cur.length()){
            choice[cur.level]&=3;
            if(cur.level)
                q.push(Node(cur.level-1,cur.spos,cur.epos));
        }
        else {
            choice[cur.level]&=(cur.sdigit+1);
            if(cur.level){
                q.push(Node(cur.level-1,cur.spos,cur.spos+cur.scnt-1));
                q.push(Node(cur.level-1,cur.spos+cur.scnt,cur.epos));
            }
        }
    }
    LL ans = 1;
    for(int i=0;i<60;i++){
        if(!choice[i]) {
            ans=0;
            break;
        }
        if(choice[i]==3) ans*=2;
    }
    printf("%lld\n",ans);
    return 0;
}

 

posted @ 2017-05-23 15:09  redips  阅读(217)  评论(0编辑  收藏  举报