Problem - E - Codeforces
题意:
思路:
这其实是一个套路题
区间异或转化成前缀异或,然后枚举 i
对于每一个 i,ai ^ x = k,对 x 计数
先建一棵字典树,然后在字典树上计数
先去对 > k 的部分计数,再对 = k 的部分计数
如果 k 的第 j 位是1,那么沿着走就行,否则对 (k >> j & 1) ^ 1的部分计数,然后继续沿着走
最后的res += cnt[p]是对 = k 的部分计数
Code:
#include <bits/stdc++.h>using i64 = long long;constexpr int N = 1e6 + 10;
constexpr int M = 1e6 + 10;
constexpr int P = 2600;
constexpr i64 Inf = 1e18;
constexpr int mod = 1e9 + 7;
constexpr double eps = 1e-6;int n, k;
int tot = 1;
int a[N], cnt[N * 30];
int tr[N * 30][2];void insert(int x) {int p = 1;for (int j = 30; j >= 0; j --) {int u = (x >> j) & 1;if (!tr[p][u]) tr[p][u] = ++tot;p = tr[p][u];cnt[p] ++;}
}
i64 query(int x, int y) {int p = 1;i64 res = 0;for (int j = 30; j >= 0; j --) {int u = (x >> j) & 1, v = (y >> j) & 1;if (v) {p = tr[p][u ^ 1];}else {res += cnt[tr[p][u ^ 1]];p = tr[p][u];}}res += cnt[p];return res;
}
void solve() {std::cin >> n >> k;for (int i = 1; i <= n; i ++) std::cin >> a[i];for (int i = 1; i <= n; i ++) a[i] ^= a[i - 1];i64 ans = 0;for (int i = 1; i <= n; i ++) {insert(a[i - 1]);ans += query(a[i], k);}std::cout << ans << "\n";
}
signed main() {std::ios::sync_with_stdio(false);std::cin.tie(nullptr);int t = 1;while (t--) {solve();}return 0;
}