?洛谷4735??BZOJ3261?最大異或和【可持久化01Trie】
阿新 • • 發佈:2019-04-11
long long include pri getchar read 異或操作 動態 struct 普通
然後我就發現了這個
真的是石樂誌了。qwq
題目鏈接
【BZOJ傳送門】
【洛谷傳送門】
題解
終於學會了可持久化trie
樹了。感覺並不是特別的難。
因為可持久化,那麽我們就考慮動態開點的trie
樹。
都知道異或操作是有傳遞性的,那麽我們就維護一個前綴異或和。
【最長異或距離】
可以參考以上這一道題目的貪心策略。
每次找到另外一邊的(說的清楚一點就是每一次找字典樹的兒子都找異或的數當前這一位的異或1
的值),這樣可以保證疑惑後答案最大。
參照主席樹的區間最小的求法:【洛谷的模板】
每一次我們就查找root[l - 1] ~ root[r]
區間內的答案就可以了。
一開始不理解可持久化01字典樹的原因是因為我不知道為什麽字典樹裏面需要有31
這個東西
31
其實就是普通字典樹裏面的字符串的長度的意思。真的是石樂誌了。qwq
那麽可持久化01trie
的模板如下
插入操作
void ins(int &rt, int pre, int val, int len) { rt = ++ tot; int k = rt; for (int i = len; ~i; i --) { ch[k][0] = ch[pre][0]; ch[k][1] = ch[pre][1]; cnt[k] = cnt[pre] + 1; int p = (val >> i) & 1; ch[k][p] = ++ tot; k = ch[k][p]; pre = ch[pre][p]; } cnt[k] = cnt[pre] + 1; }
其他的操作和普通的字典樹是一樣的。
代碼
#include <bits/stdc++.h> #pragma GCC optimize(2) #define ms(a, b) memset(a, b, sizeof(a)) #define ll long long #define ull unsigned long long #define ms(a, b) memset(a, b, sizeof(a)) #define inf 0x3f3f3f3f #define db double #define Pi acos(-1) #define eps 1e-8 #define N 600005 using namespace std; template <typename T> T power(T x, T y, T mod) { x %= mod; T res = 1; for (; y; y >>= 1) { if (y & 1) res = (res * x) % mod; x = (x * x) % mod; } return res; } template <typename T> void read(T &x) { x = 0; T fl = 1; char ch = 0; for (; ch < '0' || ch > '9'; ch = getchar()) if (ch == '-') fl = -1; for (; ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48); x *= fl; } 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 L_Trie { int ch[N * 40][2], cnt[N * 40], tot; void ins(int &rt, int pre, int val, int len) { rt = ++ tot; int k = rt; for (int i = len; ~i; i --) { ch[k][0] = ch[pre][0]; ch[k][1] = ch[pre][1]; cnt[k] = cnt[pre] + 1; int p = (val >> i) & 1; ch[k][p] = ++ tot; k = ch[k][p]; pre = ch[pre][p]; } cnt[k] = cnt[pre] + 1; } int query(int x, int y, int val, int len) { int res = 0; for (int i = len; ~i; i --) { int p = (val >> i) & 1; if (cnt[ch[y][p ^ 1]] - cnt[ch[x][p ^ 1]] > 0) { res += (1 << i); x = ch[x][p ^ 1]; y = ch[y][p ^ 1]; } else x = ch[x][p], y = ch[y][p]; } return res; } } trie; int root[N], sumxor[N]; char opt[5]; int n, m; int main() { read(n); read(m); trie.ins(root[0], root[0], 0, 31); for (int i = 1; i <= n; i ++) { int x; read(x); sumxor[i] = sumxor[i - 1] ^ x; trie.ins(root[i], root[i - 1], sumxor[i], 31); } for (int i = 1; i <= m; i ++) { scanf("%s", opt); int x, l, r; if (opt[0] == 'A') { read(x); ++ n; sumxor[n] = sumxor[n - 1] ^ x; trie.ins(root[n], root[n - 1], sumxor[n], 31); } else { read(l); read(r); read(x); l --; r --; printf("%d\n", trie.query(root[l - 1], root[r], x ^ sumxor[n], 31)); } } return 0; }
?洛谷4735??BZOJ3261?最大異或和【可持久化01Trie】