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} al−1 或大于 a r + 1 a_{r+1} ar+1,或者这个区间的前段的异或和大于后段的异或和 。由于 1 ≤ a i ≤ 1 0 9 1\le a_i \le 10^9 1≤ai≤109 ,所以 a i a_i ai 的二进制最多大约有 32 32 32 位,所以当 n ≥ 96 n\ge 96 n≥96 时, n n n 个数中最少有三个数最高位相同,取三个连续的最高位相同的数,选择后两个进行异或,得到的值一定小于第一个数,所以当 n ≥ 96 n\ge96 n≥96时,答案一定是 1 1 1 ,当 n ≤ 96 n\le 96 n≤96 时,暴力即可。
代码
#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);
}
博客解析了Codeforces上的一道题目,讨论如何通过异或操作使得非严格单调递增序列变得不满足条件。文章指出,当序列长度大于96时,至少进行一次操作,否则使用暴力搜索找到最佳操作区间。代码部分展示了实现这一策略的C++程序。
3万+

被折叠的 条评论
为什么被折叠?



