1592A - Геймер Хемосе

Codeforces Round #746 (Div.2) 题解_数组



1592B - Hemose Shopping

我们发现,在这个数组中,左右两部分是可以任意交换的。

如 :\(x = 5\), 有数组 \([7, 1, 5, 4, 3, 2, 6]\), 发现完全可以排列成\([1, 2, 5, 4, 3, 6, 7]\)

证 :\(a[i]\) 与 \(a[i + d](d < x)\), 可以通过 $ a[i + d + x] $ 实现交换,故$ [1, n - x] \cup [x + 1, n]$ 可以相当于 \(sort\)。剩下的没办法,动都动不了,只能判断是否不降, 若不降就是 \(\text{YES}\), 否则 \(\text{NO}\) 。



1592C - Bakry and Partitioning

提一嘴 :联通块数是\(2 \sim k\),不是强制 \(k\)。

可以发现,要么两个联通块, 要么三个联通块,其他的情况都等价于这两种情况。

  1. 分为两个联通块, \(\bigoplus allsum = 0\) 随便删一条边即可。
  2. 发现 \(\bigoplus allsum = \bigoplus everyblocksum\), \(dfs\) 一遍找子树 \(\bigoplus sum = \bigoplus allsum\), 统计一下,个数大于等于2即可。
    注意:已经等于\(\bigoplus allsum\)的要割掉,即返回 \(0\)。


1592E - Скучающий Бакри

易知,应该在每一位上考虑。

结论 :当一段区间有贡献,当且仅当这一段区间全为 \(1\)。证明易知。

以此结论,我们考虑每个区间 \([l, r]\) 模拟两数 \(xorsum, andsum\) 二进制位比较的过程:从高到低,某一位 \(1>0\)。

当我们比较到第 \(k\) 位时,我们所比较的 \(andsum = 1\) 时,\(xorsum\) 必然为 \(0\), 故第 \(1\) 到 \(k - 1\) 位的 \(xorsum\) 与 \(andsum\) 均为 \(0\)。

故统计当前异或和,当此时\(x\)异或和 \(\bigoplus_{begin} ^{x}\) 在以前出现过\(\bigoplus_{begin} ^{y}\)时,这一段的异或和\(\bigoplus_{y + 1} ^{x}\)为\(0\),故统计当前答案 \(x- y\) 即可。


#include <bits/stdc++.h>
using namespace std;
int read() {
int f = 1, x = 0; char c = getchar();
while(!isdigit(c)) {if(c == '-') f = -f; c = getchar();}
while(isdigit(c)) {x = (x << 1) + (x << 3) + c - '0'; c = getchar();}
return x * f;
}
const int N = 1e6 + 5;
int n, m, p, q, ans, a[N];
unordered_map <int, int> mp;
int main() {
n = read();
for(int i = 1; i <= n; i ++) a[i] = read();
for(int i = 20, sum = 0, tmp; i >= 0; sum = 0, i --) {
mp.clear(), mp[0] = 1;
for(int j = 1; j <= n; j ++) {
// cout << int((a[j] >> i) & 1) << " " ;
if(!((a[j] >> i) & 1)) {
sum = 0; mp.clear(); mp[0] = j + 1;
continue;
}
sum ^= a[j]; tmp = (sum >> i) << i;
if(!mp[tmp])
mp[tmp] = j + 1;
else
ans = max(ans, j - mp[tmp] + 1);
}
// cout << "\n";
}
cout << ans;
return 0;
}