【Codeforces】Technocup 2021 - Elimination Round 2 D. XOR-gun 思维

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_i\leq h_{i+1}\)\(a_i\leq 10^9\) ,\(h_i\) 最大为 \(30\)

所以只要 \(n >60\) 一定会存在连续三个数字的最高位相等。

\(n\leq 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\n");
        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\n");
    }else{
        printf("%d\n",ans);
    }
    return 0;
}
posted @ 2020-12-01 10:52  Valk3  阅读(90)  评论(0编辑  收藏  举报