版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39972971/article/details/89180689
【思路要点】
- 令 , 表示 处的前缀异或和。
- 则答案 为 。
- 注意到 三对数中若有两对相等,那么另一对也相等。
- 考虑容斥,令 表示所有 的字典树, 表示所有 的 的字典树, 表示所有 的 的字典树, 表示所有 的 的字典树, 表示所有 的 的字典树,在 上询问即可。
- 时间复杂度 。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXN = 6e5 + 5; const int MAXP = 4e7 + 5; typedef long long ll; typedef long double ld; typedef int long long ull; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } struct SegmentTree { struct Node { int lc, rc; int sum; } a[MAXP]; int size, depth; void init(int x) { size = 0; depth = x; } int modify(int root, int pos, int d, int depth) { if (root == 0) root = ++size; a[root].sum += d; if (depth == -1) return root; int tmp = 1 << depth; if (tmp & pos) a[root].rc = modify(a[root].rc, pos, d, depth - 1); else a[root].lc = modify(a[root].lc, pos, d, depth - 1); return root; } int modify(int root, int pos, int d) { return modify(root, pos, d, depth); } int query(int ra, int rb, int rc, int rd, int re, int val, int depth) { if (depth == -1) return 0; int tmp = 1 << depth; if (val & tmp) { if (a[a[ra].lc].sum + a[a[rb].lc].sum + a[a[rc].lc].sum + a[a[rd].lc].sum + a[a[re].lc].sum) return query(a[ra].lc, a[rb].lc, a[rc].lc, a[rd].lc, a[re].lc, val, depth - 1) + tmp; else return query(a[ra].rc, a[rb].rc, a[rc].rc, a[rd].rc, a[re].rc, val, depth - 1); } else { if (a[a[ra].rc].sum + a[a[rb].rc].sum + a[a[rc].rc].sum + a[a[rd].rc].sum + a[a[re].rc].sum) return query(a[ra].rc, a[rb].rc, a[rc].rc, a[rd].rc, a[re].rc, val, depth - 1) + tmp; else return query(a[ra].lc, a[rb].lc, a[rc].lc, a[rd].lc, a[re].lc, val, depth - 1); } } int query(int ra, int rb, int rc, int rd, int re, int val) { if (a[ra].sum + a[rb].sum + a[rc].sum + a[rd].sum + a[re].sum) return query(ra, rb, rc, rd, re, val, depth); else return 0; } } ST; int n, opt, p[MAXN], a[MAXN]; int rootall, rootx[MAXN], rooty[MAXN], rootz[MAXN]; map <pair <int, pair <int, int>>, int> rootspe; void addpoint(int x, int y, int z, int val) { rootall = ST.modify(rootall, val, 1); rootx[x] = ST.modify(rootx[x], val, -1); rooty[y] = ST.modify(rooty[y], val, -1); rootz[z] = ST.modify(rootz[z], val, -1); rootspe[make_pair(x, make_pair(y, z))] = ST.modify(rootspe[make_pair(x, make_pair(y, z))], val, 2); } int query(int x, int y, int z, int val) { return ST.query(rootall, rootx[x], rooty[y], rootz[z], rootspe[make_pair(x, make_pair(y, z))], val); } int main() { freopen("imbalance.in", "r", stdin); freopen("imbalance.out", "w", stdout); ST.init(30); read(n), read(opt); for (int i = 1; i <= n; i++) read(p[i]); for (int i = 1; i <= n; i++) read(a[i]); int lastans = 0, x = n, y = n, z = n, s = 0; addpoint(x, y, z, s); for (int i = 1; i <= n; i++) { if (opt) { p[i] = (p[i] ^ lastans) % 3; a[i] = a[i] ^ lastans; } s ^= a[i]; if (p[i] == 0) x++, y--; if (p[i] == 1) y++, z--; if (p[i] == 2) z++, x--; printf("%d ", lastans = query(x, y, z, s)); addpoint(x, y, z, s); } return 0; }