P10856 Xor-Forces 题解
首先我们发现操作
有个显然的转化:区间颜色段个数等于区间长度减去相邻同色对数,只需考虑如何计算
考虑线段树,当询问跨过区间中点
现在我们要解决的就是线段树上某个节点对应的答案,因为每次异或的
这里给出一个结论:如果一个节点对应的区间长度为
这是为什么呢?考虑询问的是
我们发现,对于
于是对于每个节点,我们只需要维护
由于线段树一共
代码中线段树的实现是左闭右开。
#include <bits/stdc++.h>
using i64 = long long;
constexpr int N = 3e5 + 5, LOG = 20;
int o, k, m, n;
int a[N], sum[N], M[LOG][N];
std::vector<int> f[N << 2];
#define ls(u) (u << 1)
#define rs(u) (u << 1 | 1)
void build(int u, int l, int r) {
int len = r - l, bit = std::__lg(len); f[u].resize(len); M[bit][l] = u;
if (len == 1) return f[u][0] = 0, void();
int mid = (l + r) >> 1;
build(ls(u), l, mid);
build(rs(u), mid, r);
for (int x = 0; x < len; x++) {
if (x < len / 2) f[u][x] = f[ls(u)][x] + f[rs(u)][x] + (a[mid ^ x] == a[(mid - 1) ^ x]);
else f[u][x] = f[ls(u)][x - (len / 2)] + f[rs(u)][x - (len / 2)] + (a[mid ^ x] == a[(mid - 1) ^ x]);
}
}
int query(int u, int l, int r, int ql, int qr, int y) {
int bit = std::__lg(r - l);
if (ql <= l && r - 1 <= qr) return f[M[bit][l ^ (y >> bit << bit)]][y % (1 << bit)];
int mid = (l + r) >> 1, L = 0, R = 0; bool fL = false, fR = false;
if (ql < mid) L = query(ls(u), l, mid, ql, qr, y), fL = true;
if (qr >= mid) R = query(rs(u), mid, r, ql, qr, y), fR = true;
return fL ? (fR ? L + R + (a[mid ^ y] == a[(mid - 1) ^ y]) : L) : R;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cin >> o >> k >> m; n = (1 << k);
for (int i = 0; i < n; i++) std::cin >> a[i];
build(1, 0, n);
int lst = 0, y = 0;
for (int i = 1; i <= m; i++) {
int op; std::cin >> op;
if (op == 1) {
int x; std::cin >> x; x ^= (o * lst);
y ^= x;
}
if (op == 2) {
int l, r; std::cin >> l >> r; l ^= (o * lst), r ^= (o * lst);
if (l > r) std::swap(l, r);
std::cout << (lst = r - l + 1 - query(1, 0, n, l, r, y)) << "\n";
}
}
return 0;
}