可持久化字典树
Posted cjlhy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了可持久化字典树相关的知识,希望对你有一定的参考价值。
#include<cstdio> #include<vector> #include<algorithm> #include<cstring> #define LL long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ull unsigned long long using namespace std; const int N = 5e4 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1000000007; const double eps = 1e-6; const double PI = acos(-1); int n, q, a[N]; char op[10]; namespace Trie { int to[32][2], Rt[N], tot; int ch[N * 32][2], cnt[N * 32]; void init() { tot = 0; for(int i = 0; i <= 30; i++) to[i][0] = 0, to[i][1] = 1; } inline void cpy(int x, int y) { ch[x][0] = ch[y][0]; ch[x][1] = ch[y][1]; cnt[x] = cnt[y]; } void Insert(int v, int x, int y) { cpy(x, y); for(int i = 30; i >= 0; i--) { if(v >> i & 1 || to[i][0] == to[i][1]) { ch[x][1] = ++tot; x = ch[x][1]; y = ch[y][1]; cpy(x, y); } else { ch[x][0] = ++tot; x = ch[x][0]; y = ch[y][0]; cpy(x, y); } cnt[x]++; } } void Rebuild(int *a, int n) { tot = 0; for(int i = 1; i <= n; i++) { Rt[i] = ++tot; Insert(a[i], Rt[i], Rt[i - 1]); } } int Query(int L, int R, int K) { int ans = 0, x = Rt[R], y = Rt[L - 1]; for(int i = 30; i >= 0; i--) { bool op = !(to[i][0] < to[i][1]); if(cnt[ch[x][op]] - cnt[ch[y][op]] >= K) { ans += to[i][op] << i; x = ch[x][op]; y = ch[y][op]; } else { K -= cnt[ch[x][op]] - cnt[ch[y][op]]; ans += to[i][!op] << i; x = ch[x][!op]; y = ch[y][!op]; } } return ans; } void Or(int x) { bool need = false; for(int i = 0; i <= 30; i++) { if(x >> i & 1) { if(to[i][0] ^ to[i][1]) need = true; to[i][0] = to[i][1] = 1; } } if(need) Rebuild(a, n); } void And(int x) { bool need = false; for(int i = 0; i <= 30; i++) { if(!(x >> i & 1)) { if(to[i][0] ^ to[i][1]) need = true; to[i][0] = to[i][1] = 0; } } if(need) Rebuild(a, n); } void Xor(int x) { for(int i = 0; i <= 30; i++) if(x >> i & 1) to[i][0] ^= 1, to[i][1] ^= 1; } } int main() { // freopen("text.in", "r", stdin); scanf("%d%d", &n, &q); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); Trie::init(); Trie::Rebuild(a, n); while(q--) { scanf("%s", op); if(op[0] == ‘O‘) { int x; scanf("%d", &x); Trie::Or(x); } else if(op[0] == ‘A‘ && op[1] == ‘n‘) { int x; scanf("%d", &x); Trie::And(x); } else if(op[0] == ‘X‘) { int x; scanf("%d", &x); Trie::Xor(x); } else { int L, R, K; scanf("%d%d%d", &L, &R, &K); printf("%d ", Trie::Query(L, R, K)); } } return 0; } /* */
以上是关于可持久化字典树的主要内容,如果未能解决你的问题,请参考以下文章