题解:P11160 【MX-X6-T6】機械生命体
Loyal_Soldier · · 题解
思路
如果你不会 01Trie 全局加
首先从低位到高位建 01Trie。
操作一和操作二是简单的。
对于操作三,就是沿
由于只有子树加和判断当前子树是否为空,维护子树大小即可。
子树加
如果
对于子树加,我们考虑将这棵子树分裂出来进行全局加,然后再合并回去,如果你不会 Trie 树合并,可以先做这题。
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN = 3e5 + 10;
const int MAXM = 3e7 + 10;
const int MAXH = 31;
int n;
int ch[MAXM][2], siz[MAXM], lzy[MAXM];
int cnt, root;
void pushup(int u) {
if (!u) return;
siz[u] = siz[ch[u][0]] + siz[ch[u][1]];
}
void pushdown(int u) {
if (!u) return;
if (lzy[u] & 1) {
swap(ch[u][1], ch[u][0]);
if (ch[u][0]) lzy[ch[u][0]]++;
lzy[u]--;
}
if (ch[u][0]) lzy[ch[u][0]] += lzy[u] / 2;
if (ch[u][1]) lzy[ch[u][1]] += lzy[u] / 2;
lzy[u] = 0;
}
void insert(int &u, int x, int dep) {
if (!u) u = ++cnt;
if (dep > MAXH) {
siz[u]++;
return;
}
pushdown(u);
insert(ch[u][x & 1], x >> 1, dep + 1);
pushup(u);
}
void erase(int &u, int x, int dep) {
if (!u) u = ++cnt;
if (dep > MAXH) {
siz[u]--;
return;
}
pushdown(u);
erase(ch[u][x & 1], x >> 1, dep + 1);
pushup(u);
}
void merge(int &u, int v, int dep) {
if (!u || !v) {
u += v;
return;
}
if (dep > MAXH) {
siz[u] += siz[v];
return;
}
pushdown(u), pushdown(v);
merge(ch[u][0], ch[v][0], dep + 1);
merge(ch[u][1], ch[v][1], dep + 1);
pushup(u);
}
void split(int &u, int &v, int x, int dep, int k) {
if (!u) return;
if (dep == k) {
v = u, u = 0;
return;
}
if (!v) v = ++cnt;
pushdown(u);
split(ch[u][x & 1], ch[v][x & 1], x >> 1, dep + 1, k);
pushup(u), pushup(v);
}
int query(int u, int x, int dep) {
pushdown(u);
if (dep > MAXH) return 32;
if (!siz[ch[u][x & 1]]) return dep;
return query(ch[u][x & 1], x >> 1, dep + 1);
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n;
while (n--) {
int op, x;
cin >> op >> x;
if (op == 1) insert(root, x, 0);
else if (op == 2) erase(root, x, 0);
else if (op == 3) {
int k, v;
cin >> k >> v;
int qwq = 0;
split(root, qwq, x, 0, k);
if (qwq) lzy[qwq] += v;
merge(root, qwq, 0);
} else cout << (1ll << query(root, x, 0)) << '\n';
}
return 0;
}