【分类讨论】CF1747D

Problem - D - Codeforces

题意

思路

一看这个做法一定就是分类讨论

先判无解

显然,如果区间异或和不是0一定无解

如果区间内全是0,答案一定是0

之后怎么讨论

注意到需要讨论区间长度

如果长度是奇数,那么直接操作即可,答案一定是1

else 如果是偶数,需要看是否存在一个分割点使得一个区间可以分割成两个区间,两个区间的区间异或和都是0

这点有点难注意到,我们很容易地会以为如果一个区间的异或和是0,一定存在分割点,其实不一定,这点需要记住

那么问题就是如何找这个分割点

这个分割点假设是 k, 需要满足pre[l - 1] == pre[k] 且 位置的奇偶性要和 l 一致,因为区间长度要是奇数,那么就是去找后面第一个满足这个条件的就行

那么就是把所有前缀异或和为 pre[l - 1]和位置的奇偶性放进集合里,二分查找即可

Code:

#include <bits/stdc++.h>

#define int long long

constexpr int N = 2e5 + 10;
constexpr int mod = 998244353;

std::map<int, std::vector<int> > S[2];

int n, q;
int a[N];
int pre[N];
int s[N];

int get(int l, int r) {
	return pre[r] ^ pre[l - 1];
}
void solve() {
	std::cin >> n >> q;
	pre[0] = 0;
	for (int i = 1; i <= n; i ++) {
		std::cin >> a[i];
		pre[i] = pre[i - 1] ^ a[i];
		s[i] = s[i - 1] + (a[i] == 0);
		S[i & 1][pre[i]].push_back(i);
	}
	while(q --) {
		int l, r;
		std::cin >> l >> r;
		if (get(l, r) != 0) {
			std::cout << -1 << "\n";
			continue;
		}
		if (s[r] - s[l - 1] == r - l + 1) {
			std::cout << 0 << "\n";
			continue;
		}
		if ((r - l + 1) % 2 == 1 ||((r - l + 1) % 2 == 0 && (a[l] == 0 || a[r] == 0))) {
			std::cout << 1 << "\n";
		}else {
			auto it = std::lower_bound(S[l & 1][pre[l - 1]].begin(), S[l & 1][pre[l - 1]].end(), l);
			if (it != S[l & 1][pre[l - 1]].end() && *it < r) {
				std::cout << 2 << "\n";
			}else {
				std::cout << -1 << "\n";
			}
		}
	}
}
signed main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);

	int t = 1;
	while (t--) {
		solve();
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值