Description
Solution
设原始数组为
a
a
a, 设
b
i
b_i
bi 为
a
i
a_i
ai 的二进制位数
若存在一个
i
i
i,满足
b
i
−
1
=
b
i
=
b
i
+
1
b_{i-1} = b_{i} = b_{i+1}
bi−1=bi=bi+1,则我们只需要将后两个数异或,得到的数一定比
a
i
−
1
a_{i-1}
ai−1小(因为最高位变成0了)
若这样的
i
i
i 不存在,则原始数组的长度一定不超过 2*30 = 60,
我们暴力计算
n
≤
60
n \leq 60
n≤60 的情况:
最后的答案数组一定存在两个相邻两个数是严格递减,而这两个数是由原始数组中两个相邻段连续异或而成的
故我们枚举l,r,k, 代表将a[l,k]异或起来以及将a[k+1,r] 异或起来,是否满足两个数递减的关系
复杂度 O ( n 4 ) O(n^4) O(n4),若预处理出前缀异或和则可优化到 O ( n 3 ) O(n^3) O(n3)
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 7;
int a[maxn];
int pre[maxn];
int f(int l,int r) {
if(l > r) return 0;
return pre[r] ^ pre[l-1];
}
int main() {
int n;scanf("%d",&n);
for(int i = 1;i <= n;++i) {
scanf("%d",&a[i]);
}
if(n > 60) {printf("1\n");return 0;}
int res = maxn;
for(int i = 1;i <= n;++i) pre[i] = pre[i-1] ^ a[i];
for(int l = 1;l < n;++l) {
for(int r = l + 1;r <= n;++r) {
int d1 = 0,d2 = 0;
for(int k = l;k < r;++k) {
d1 = f(l,k), d2 = f(k+1,r);
if(d1 > d2) res = min(res, (k-l+ r-(k+1)));
}
}
}
if(res == maxn) res = -1;
printf("%d\n", res);
return 0;
}