- 玄关求调
P3391 【模板】文艺平衡树
- @ 2025-8-22 14:29:31
// 【模板】文艺平衡树
#include <cstdio>
#include <cstdlib>
#define lc son[p][0]
#define rc son[p][1]
const int N = 1e5 + 37;
int n, m, idx, root;
int son[N][2], val[N], siz[N], pri[N], tag[N];
void swap(int &x, int &y) {
int z = x;
x = y;
y = z;
}
void up(int p) { siz[p] = siz[lc] + siz[rc] + 1; }
void down(int p) {
if (!tag[p]) return;
swap(son[p][0], son[p][1]);
tag[lc] ^= 1, tag[rc] ^= 1;
tag[p] = 0;
}
void split(int p, int v, int &l, int &r) {
if (!p) {
l = r = 0;
return;
}
down(p);
if (siz[lc] < v) {
l = p;
split(rc, v - siz[lc] - 1, rc, r);
} else {
r = p;
split(lc, v, l, lc);
}
}
int merge(int l, int r) {
if (!l || !r) return l + r;
if (pri[l] > pri[r]) {
down(l);
son[l][1] = merge(son[l][1], r);
up(l);
return l;
} else {
down(r);
son[r][0] = merge(l, son[r][0]);
up(r);
return r;
}
}
int insert(int v) {
int p = ++idx, l, r;
split(root, v, l, r);
pri[p] = rand();
val[p] = v;
siz[p] = 1;
root = merge(merge(l, p), r);
}
void dfs(int p) {
if (!p) return;
down(p);
dfs(lc);
printf("%d ", p);
dfs(rc);
}
int main()
{
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++) insert(i);
for (int i = 1, ll, rr; i <= m; i++) {
scanf("%d %d", &ll, &rr);
int p, l, r;
split(root, rr, l, r);
split(l, ll - 1, l, p);
tag[p] ^= 1;
root = merge(merge(l, p), r);
}
dfs(root);
return 0;
}
3 条评论
-
-
#include <cstdio> #include <cstdlib> #define lc son[p][0] #define rc son[p][1] const int N = 1e5 + 37; int n, m, idx, root; int son[N][2], val[N], siz[N], pri[N], tag[N]; void swap(int &x, int &y) { int z = x; x = y; y = z; } void up(int p) { siz[p] = siz[lc] + siz[rc] + 1; } void down(int p) { if (!tag[p]) return; swap(son[p][0], son[p][1]); tag[lc] ^= 1, tag[rc] ^= 1; tag[p] = 0; } void split(int p, int v, int &l, int &r) { if (!p) { l = r = 0; return; } down(p); if (siz[lc] < v) { l = p; split(rc, v - siz[lc] - 1, rc, r); } else { r = p; split(lc, v, l, lc); } up(p); } int merge(int l, int r) { if (!l || !r) return l + r; if (pri[l] > pri[r]) { down(l); son[l][1] = merge(son[l][1], r); up(l); return l; } else { down(r); son[r][0] = merge(l, son[r][0]); up(r); return r; } } void insert(int v) { int p = ++idx, l, r; split(root, v, l, r); pri[p] = rand(); val[p] = v; siz[p] = 1; root = merge(merge(l, p), r); } void dfs(int p) { if (!p) return; down(p); dfs(lc); printf("%d ", p); dfs(rc); } int main() { scanf("%d %d", &n, &m); for (int i = 1; i <= n; i++) insert(i); for (int i = 1, ll, rr; i <= m; i++) { scanf("%d %d", &ll, &rr); int p, l, r; split(root, rr, l, r); split(l, ll - 1, l, p); tag[p] ^= 1; root = merge(merge(l, p), r); } dfs(root); return 0; } -
#include <cstdio> #include <cstdlib> #define lc son[p][0] #define rc son[p][1] const int N = 1e5 + 37; int n, m, idx, root; int son[N][2], val[N], siz[N], pri[N], tag[N]; void swap(int &x, int &y) { int z = x; x = y; y = z; } void up(int p) { siz[p] = siz[lc] + siz[rc] + 1; } void down(int p) { if (!tag[p]) return; swap(son[p][0], son[p][1]); tag[lc] ^= 1, tag[rc] ^= 1; tag[p] = 0; } void split(int p, int v, int &l, int &r) { if (!p) { l = r = 0; return; } down(p); if (siz[lc] < v) { l = p; split(rc, v - siz[lc] - 1, rc, r); up(p); // 修改:在递归后更新 } else { r = p; split(lc, v, l, lc); up(p); // 修改:在递归后更新 } } int merge(int l, int r) { if (!l || !r) return l + r; if (pri[l] > pri[r]) { down(l); son[l][1] = merge(son[l][1], r); up(l); return l; } else { down(r); son[r][0] = merge(l, son[r][0]); up(r); return r; } } int insert(int v) { int p = ++idx; pri[p] = rand(); val[p] = v; siz[p] = 1; int l, r; split(root, v, l, r); // 在位置 v 处分割?但这里的 v 是值,且作为大小,但当树较小时,会以完整大小分割 root = merge(merge(l, p), r); } void dfs(int p) { if (!p) return; down(p); dfs(lc); printf("%d ", val[p]); // 输出值或 p 都可以,但更安全是输出 p // 但这里 val[p] 应该与 p 相同,输出 p 也可以 dfs(rc); } int main() { scanf("%d %d", &n, &m); for (int i = 1; i <= n; i++) insert(i); for (int i = 1, ll, rr; i <= m; i++) { scanf("%d %d", &ll, &rr); int l, r, p; split(root, rr, l, r); split(l, ll - 1, l, p); tag[p] ^= 1; root = merge(merge(l, p), r); } dfs(root); return 0; }
- 1