D. Yet Another Problem
D. Yet Another Problem
You are given an array of integers .
You have to answer independent queries, each consisting of two integers and .
- 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 XOR of the elements in the subarray .
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 XOR operation here.
Input
The first line contains two integers and — the length of the array and the number of queries.
The next line contains integers — the elements of the array .
The -th of the next lines contains two integers and — the description of the -th query.
Output
For each query, output a single integer — the answer to that query.
Example
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, ,, subarray . We can apply operation only to the subarrays of length , which won't change the array; hence it is impossible to make all elements equal to .
In the second query, ,, subarray . We can choose the whole subarray and replace all elements by their XOR , making the subarray .
In the fifth query, ,, subarray . We can make the operations as follows:
- Choose ,, making the subarray .
- Choose ,, making the subarray .
解题思路
这题最关键的地方是要看出来每一次操作都不会改变整个区间的异或和。
这是因为每次都选择一个长度为奇数的区间,然后将这个奇数区间中的每一个元素用奇数区间的异或和来代替,此时再求变化后的整个区间的异或和,可以发现此时的奇数区间的异或和结果就是原来没操作前的异或和,再异或上其他的元素就可以发现整个区间的异或和就是原来数组的异或和。
因此现在就可以判断出无解的情况。由于最后整个区间都要变成,等价于整个区间的异或和为,又因为每次操作都不会改变整个区间的异或和,因此如果整个区间的异或和不为就无解。
接下来讨论的都是整个区间异或和为的情况。
如果此时区间的全部元素均为,那么只需要操作次。
如果此时询问的区间长度为奇数,由于整个区间的异或和为,因此只需操作次(选择整个区间)。
如果区间的长度为偶数:
如果最左边的元素为或最右边的元素为,那么只需操作次。
否则,我们找一下是否存在某个长度为奇数的前缀,这个前缀的异或和为,如果存在,那么剩余部分(长度为奇数)的异或和也为。再找一下是否存在某个长度为奇数的后缀,这个后缀的异或和为,如果存在,那么剩余部分(长度为奇数)的异或和也为。需要操作次。
可以发现我们只需要看前缀就可以了,不需要把后缀的情况再考虑一遍。这是因为如果前缀的异或和为,那么剩余部分就是奇数的后缀,而剩余的部分的异或和也为,意味着存在一个奇数的后缀的异或和为。即如果存在一个奇数的前缀的异或和为,那么必然会存在一个奇数的后缀的异或和为。为什么只判断前缀这种做法是对的呢,这是因为我们要把左端点的值变成,意味着必然要对某个奇数的前缀进行操作。
那么如何找到是否存在某个前缀的异或和为。假设有异或前缀和,询问的区间是,那么这个问题等价于找到一个且的奇偶性与相同,使得,等价找到一个使得。那么我们可以一开始开两个哈希表,根据下标的奇偶性来记录异或前缀和为时所对应的下标,到时候就可以二分出异或前缀和等于的下标,最后看一下这个下标是否在范围内就可以了。
AC代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 6 const int N = 2e5 + 10; 7 8 int a[N], sx[N]; 9 LL s[N]; 10 11 int main() { 12 int n, m; 13 scanf("%d %d", &n, &m); 14 unordered_map<int, vector<int>> odd, even; 15 for (int i = 1; i <= n; i++) { 16 scanf("%d", a + i); 17 s[i] = s[i - 1] + a[i]; 18 sx[i] = sx[i - 1] ^ a[i]; 19 if (i & 1) odd[sx[i]].push_back(i); 20 else even[sx[i]].push_back(i); 21 } 22 23 while (m--) { 24 int l, r; 25 scanf("%d %d", &l, &r); 26 int ret = -1; 27 if (sx[r] ^ sx[l - 1]) { 28 ret = -1; 29 } 30 else if (s[r] - s[l - 1] == 0) { 31 ret = 0; 32 } 33 else if (r - l + 1 & 1) { 34 ret = 1; 35 } 36 else if (a[l] == 0 || a[r] == 0) { 37 ret = 1; 38 } 39 else { 40 if (l & 1) { 41 auto t = lower_bound(odd[sx[l - 1]].begin(), odd[sx[l - 1]].end(), l); 42 if (t != odd[sx[l - 1]].end() && *t <= r) ret = 2; 43 } 44 else { 45 auto t = lower_bound(even[sx[l - 1]].begin(), even[sx[l - 1]].end(), l); 46 if (t != even[sx[l - 1]].end() && *t <= r) ret = 2; 47 } 48 } 49 printf("%d\n", ret); 50 } 51 52 return 0; 53 }
参考资料
Codeforces Round #832 (Div. 2) A - D:https://zhuanlan.zhihu.com/p/580560085
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/16884740.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效