其实很早之前就想学习可持久化trie,不过由于换队友等情况,还是优先去学数论和计算几何,今天突然心血来潮学了一发可持久化trie,感觉还是蛮简单的,不过由于自己很长时间没写过可持久化了,都快忘了是个什么套路了。
具体来说,就是每次插入一个数,我们先判断这一位是0还是1,然后把以前节点里面和这一位相反的那个子节点接到我们现在要插入的新节点上面去,然后呢,你就可以直接递归的构造之后的子树。并且我们每到新的一层,都会记录这个节点所代表的的位数在当前这个位置已经出现了多少次,那么我们查询的时候,就能判断一个区间里面是否有这一位了,理解之后感觉随便写写就能出来,记个代码。
//author Eterna #define Hello the_cruel_world! #pragma GCC optimize(2) #include<iostream> #include<algorithm> #include<cstdio> #include<string> #include<cstring> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<utility> #include<cmath> #include<climits> #include<deque> #include<functional> #include<complex> #include<numeric> #include<unordered_map> #define max(x,y) ((x)>(y)?(x):(y)) #define min(x,y) ((x)<(y)?(x):(y)) #define Pi acos(-1.0) #define ABS(x) ((x) >= 0 ? (x) : (-(x))) #define pb(x) push_back(x) #define lowbit(x) (x & -x) #define FRIN freopen("C:\\Users\\Administrator.MACHENI-KA32LTP\\Desktop\\in.txt", "r", stdin) #define FROUT freopen("C:\\Users\\Administrator.MACHENI-KA32LTP\\Desktop\\out.txt", "w", stdout) #define FAST ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); #define outd(x) printf("%d\n", x) #define outld(x) printf("%lld\n", x) #define il inline #define ls(x) arr[x].child[0] #define rs(x) arr[x].child[1] using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; const int maxn = 6e5; const int INF = 0x7fffffff; const int mod = 1e9 + 7; const double eps = 1e-7; inline int read_int() { char c; int ret = 0, sgn = 1; do { c = getchar(); } while ((c < ‘0‘ || c > ‘9‘) && c != ‘-‘); if (c == ‘-‘) sgn = -1; else ret = c - ‘0‘; while ((c = getchar()) >= ‘0‘ && c <= ‘9‘) ret = ret * 10 + (c - ‘0‘); return sgn * ret; } inline ll read_ll() { char c; ll ret = 0, sgn = 1; do { c = getchar(); } while ((c < ‘0‘ || c > ‘9‘) && c != ‘-‘); if (c == ‘-‘) sgn = -1; else ret = c - ‘0‘; while ((c = getchar()) >= ‘0‘ && c <= ‘9‘) ret = ret * 10 + (c - ‘0‘); return sgn * ret; } struct node { int child[2], cnt; }arr[26 * maxn + 5]; int tot, coe[30], root[maxn + 5]; void Insert(int& now, int pre, int v, int cnt = 24) { if (!now)now = ++tot; arr[now].cnt = arr[pre].cnt + 1; if (cnt < 0)return; int p = (v >> cnt) & 1; arr[now].child[p ^ 1] = arr[pre].child[p ^ 1]; Insert(arr[now].child[p], arr[pre].child[p], v, cnt - 1); } int Query(int l, int r, int v, int cnt = 24) { if (cnt < 0)return 0; int p = (v >> cnt) & 1; int sum = arr[arr[r].child[p ^ 1]].cnt - arr[arr[l].child[p ^ 1]].cnt; if (sum > 0)return coe[cnt] + Query(arr[l].child[p ^ 1], arr[r].child[p ^ 1], v, cnt - 1); else return Query(arr[l].child[p], arr[r].child[p], v, cnt - 1); } int n, m, a[maxn + 5]; char op; int main() { coe[0] = 1; for (int i = 1; i < 30; ++i)coe[i] = coe[i - 1] * 2; n = read_int() + 1, m = read_int(); Insert(root[1], root[0], 0); for (int i = 1; i < n; ++i) { a[i] = read_int(); a[i] ^= a[i - 1]; Insert(root[i + 1], root[i], a[i]); } while (m--) { scanf(" %c", &op); if (op == ‘A‘) { a[n] = a[n - 1]; a[n++] ^= read_int(); Insert(root[n], root[n - 1], a[n - 1]); } else { int l = read_int(), r = read_int(), x = read_int(); printf("%d\n", Query(root[l - 1], root[r], a[n - 1] ^ x)); } } //system("pause"); return 0; }
原文:https://www.cnblogs.com/Eterna-King/p/10547041.html