题目 | Yet Another Problem
Codeforces Round #832 (Div. 2)
D. Yet Another Problem
https://codeforces.com/contest/1747/problem/D
1 seconds / 256 megabytes
standard input / standard output
Problem
You are given an array
You have to answer
Consider the subarray
. You can apply the following operation to the subarray any number of times (possibly zero)-- Choose two integers
, such that and is odd. - Replace each element in the subarray from
to with the of the elements in the subarray .
- Choose two integers
- The answer to the query is the minimum number of operations required to make all elements of the subarray
equal to or if it is impossible to make all of them equal to .
You can find more details about
Input
The first line contains two integers
The next line contains
The
Output
For each query, output a single integer — the answer to that query.
Example
input
7 6
3 0 3 3 1 2 3
3 4
4 6
3 7
5 6
1 6
2 2
output
-1
1
1
-1
2
0
Note
In the first query,
In the second query,
In the fifth query,
- Choose
, making the subarray . - Choose
, making the subarray .
题解
操作前后区间的异或值不变
该题的突破口就在“操作区间长度为奇数”这个条件上,通过分析可以得到上述结论。具体推导如下:
设长度为奇数
对于任意数
那么原区间的异或值为
即原区间异或值与操作后异或值相同
若区间异或值不为 ,则无解
对于一个区间,每一次操作都不会改变区间异或值。若区间能够变为全
注意上述结论,异或值为
进行分类讨论
情况数目很多,需要仔细分类。
- 区间异或值非零:无解,输出
区间异或值为零
- 若区间全零:无需操作,即操作次数为
若区间含非零元素
- 区间长度为奇数:对整个区间进行操作即可,操作次数为
区间长度为偶数
- 区间首(或尾)为零:对除了尾(或头)的字区间进行操作即可,操作次数为
区间首尾非零
- 区间可分为两个异或值为零的长度为奇数的子区间:对两个子区间分别进行一次操作即可,操作次数为
- 不能分为上述两个子区间:无解,输出
- 区间可分为两个异或值为零的长度为奇数的子区间:对两个子区间分别进行一次操作即可,操作次数为
- 区间首(或尾)为零:对除了尾(或头)的字区间进行操作即可,操作次数为
- 区间长度为奇数:对整个区间进行操作即可,操作次数为
- 若区间全零:无需操作,即操作次数为
求解区间异或值
可以借鉴前缀和思想,求出区间的前缀异或
- 初始化时间复杂度:
- 查询时间复杂度:
判断区间是否全零
可以记录一个数组
- 初始化时间复杂度:
- 查询时间复杂度:
判断偶数长度区间是否可分为两个异或值为零的长度为奇数的子区间
可以记录以该下标为右界的长度为奇数的异或值为零的区间的最大左界。若
若区间
注意我们要保证切分出来的两个区间均为奇数区间,因此若右界为偶数下标,则左界为奇数下标,反之亦然。
- 初始化时间复杂度:
- 查询时间复杂度:
关于 I/O 方式
该题输入输出量较大,需要取消同步流,其次需要注意将 endl
替换为 \n
取消刷新缓存区,否则很有可能卡线过。
正常运行时长在 300ms 左右。
代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 10;
int n, q;
int a[MAXN], prexor[MAXN], last_positive[MAXN], last_same_prexor[MAXN];
map<int, int> odd, even;
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> q;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
prexor[i] = prexor[i - 1] ^ a[i];
last_positive[i] = a[i] ? i : last_positive[i - 1];
if (i % 2)
{
if (even.count(prexor[i]))
last_same_prexor[i] = even[prexor[i]];
odd[prexor[i]] = i;
}
else
{
if (odd.count(prexor[i]))
last_same_prexor[i] = odd[prexor[i]];
even[prexor[i]] = i;
}
}
while (q--)
{
int l, r;
cin >> l >> r;
if (prexor[l - 1] ^ prexor[r])
cout << -1 << '\n';
else if (last_positive[r] < l)
cout << 0 << '\n';
else if ((r - l + 1) % 2)
cout << 1 << '\n';
else if (!a[l] || !a[r])
cout << 1 << '\n';
else if (last_same_prexor[r] >= l)
cout << 2 << '\n';
else
cout << -1 << '\n';
}
return 0;
}
本文采用 CC BY-SA 4.0 许可,本文 Markdown 源码:Haotian-BiJi