CF1457D-XOR-gun

题意

给出一个长度为 \(n\) 非递减的序列 \(a\),可以执行操作一次或者多次:选择两个相邻的数字将他们删去,并在此位置添加他们的异或和。问最少需要多少次操作使序列不是非递减的?

$2≤n≤105,1≤a_i≤109 $

分析

首先,可以发现,当连续 \(3\) 个数的最高位相同时,必然可以通过将其中两个数异或来达到目的。结合序列非递减的条件,可以得出当 \(n>60\) 时,答案必然为 \(1\)

对于 \(n\leq 60\) 的情况,我们直接枚举需要异或合并的区间一定是连续的。那么,就可以枚举区间的左右端点,然后再枚举区间的断点,比较断点两边的数是否满足要求,求出最小值即可。

代码

#include <bits/stdc++.h>

using namespace std;
const int N=1e5+5;
int a[N];
int sum[N];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    if(n>60)//必然有连续3个数的最高位相同
        printf("1\n");
    else
    {
        int ans=n+1;
        sum[0]=0;
        for(int i=1;i<=n;i++)
            sum[i]=sum[i-1]^a[i];
        for(int i=1;i<=n;i++)
        {
            for(int j=i+2;j<=n;j++)
            {
                for(int k=i;k<j;k++)
                {
                    int x=sum[k]^sum[i-1];
                    int y=sum[j]^sum[k];
                    if(x>y)
                        ans=min(ans,j-i-1);
                }
            }
        }
        printf("%d\n",ans==n+1?-1:ans);
    }
    return 0;
}
/*
4
11 22 71 92
*/

posted @ 2020-12-02 16:52  xzx9  阅读(111)  评论(0编辑  收藏  举报