D. XOR-gun

博客解析了Codeforces上的一道题目,讨论如何通过异或操作使得非严格单调递增序列变得不满足条件。文章指出,当序列长度大于96时,至少进行一次操作,否则使用暴力搜索找到最佳操作区间。代码部分展示了实现这一策略的C++程序。

Problem - D. XOR-gun- Codeforces

题意

n n n 个非严格单调递增的数,每次你可以选择两个相邻的数 a i , a i + 1 a_i,a_{i+1} ai,ai+1,把这两个数变为一个数 a i   x o r   a i + 1 a_i\space xor \space a_{i+1} ai xor ai+1 ,问最少进行几次操作可以让这个序列不满足非严格单调递增。

解法

显然选择的数一定是一个连续的区间,也就是选择一个最短的区间 [ l , r ] [l,r] [l,r],这个区间的异或和小于 a l − 1 a_{l-1} al1 或大于 a r + 1 a_{r+1} ar+1,或者这个区间的前段的异或和大于后段的异或和 。由于 1 ≤ a i ≤ 1 0 9 1\le a_i \le 10^9 1ai109 ,所以 a i a_i ai 的二进制最多大约有 32 32 32 位,所以当 n ≥ 96 n\ge 96 n96 时, n n n 个数中最少有三个数最高位相同,取三个连续的最高位相同的数,选择后两个进行异或,得到的值一定小于第一个数,所以当 n ≥ 96 n\ge96 n96时,答案一定是 1 1 1 ,当 n ≤ 96 n\le 96 n96 时,暴力即可。

代码
#pragma region
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>
using namespace std;
typedef long long ll;
#define tr t[root]
#define lson t[root << 1]
#define rson t[root << 1 | 1]
#define rep(i, a, n) for (int i = a; i <= n; ++i)
#define per(i, a, n) for (int i = n; i >= a; --i)
#pragma endregion
const int maxn = 2e5 + 5;
int n, a[maxn];
int pre[maxn];
int main() {
    scanf("%d", &n);
    rep(i, 1, n) scanf("%d", &a[i]), pre[i] = pre[i - 1] ^ a[i];
    if (n >= 96) return 0 * puts("1");
    int ans = 0x3f3f3f3f;
    rep(l, 1, n) {
        rep(r, l + 1, n) {
            rep(k, l, r - 1) {
                int tp1 = pre[k] ^ pre[l - 1], tp2 = pre[r] ^ pre[k];
                if (tp1 > tp2) ans = min(ans, r - l - 1);
                int tp3 = tp1 ^ tp2;
                if (l != 1 && tp3 < a[l - 1]) ans = min(ans, r - l);
                if (r != n && tp3 > a[r + 1]) ans = min(ans, r - l);
            }
        }
    }
    printf("%d\n", ans == 0x3f3f3f3f ? -1 : ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值