Codeforces Round #746 (Div.2) 题解

标签 :题解


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

此处输入图片的描述


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;
}
posted @ 2021-10-04 15:08  永远_少年  阅读(135)  评论(0编辑  收藏  举报