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; }