Technocup 2021 - Elimination Round 2 D. XOR-gun
题意
给出一个长度为 (n) 非递减的序列 (a),现在可以执行以下操作一次或者多次:
选择两个相邻的数字将他们删去,并在此位置添加他们的异或和。
问最少需要多少次操作使得,序列不是非递减的。
题解
定义 (h_i) 为 (a_i) 的最高位下标。
因为序列是非递减,可知 : (h_i leq h_{i+1})
如果存在 (h_{i-1} = h_i =h_{i+1}) ,就可以选择一次操作,将 (a_i) 和 (a_{i+1}) 异或。
这样就满足 (a_{i-1} > a_{i})
因为 (h_ileq h_{i+1}),(a_ileq 10^9) ,(h_i) 最大为 (30)。
所以只要 (n >60) 一定会存在连续三个数字的最高位相等。
当 (nleq 60) 时,我们可以暴力枚举。
操作区间 ([l,m]) 和 ([m+1,r]) 使得,(a_l > a_{l+1})
代码
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
const int seed=233;
const int N=1e5+10;
int arr[N],brr[N];
int get(int l,int r)
{
return brr[l-1]^brr[r];
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&arr[i]);
brr[i]=brr[i-1]^arr[i];
}
if(n>60){
printf("1
");
return 0;
}
int ans=inf;
for(int i=1;i<=n;i++){
for(int j=i;j<n;j++){
int pre=get(i,j);
for(int k=j+1;k<=n;k++){
if(get(j+1,k)<pre){
ans=min(ans,k-i-1);
}
}
}
}
if(ans==inf){
printf("-1
");
}else{
printf("%d
",ans);
}
return 0;
}