zoukankan      html  css  js  c++  java
  • [Bzoj3223][Tyvj1729] 文艺平衡树(splay/无旋Treap)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3223

    平衡树处理区间问题的入门题目,普通平衡树那道题在维护平衡树上是以每个数的值作为维护的标准,而处理区间问题时,维护平衡树的应该是每个位置的下标,所以平衡树中序遍历时应该是当前区间的样子。例如:

    {1 2 3 4 5}翻转区间1 3,则中序遍历应该输出{3,2,1,4,5}。

    提供splay和无旋Treap的题解。

    splay做法:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int inf = 2e9;
     5 const int maxn = 100010;
     6 int ch[maxn][2], siz[maxn], lazy[maxn], fa[maxn], val[maxn];
     7 int a[maxn];
     8 int root, cnt;
     9 void pushup(int x) {
    10     siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1;
    11 }
    12 void pushdown(int x) {
    13     if (lazy[x]) {
    14         if (ch[x][0])lazy[ch[x][0]] ^= 1;
    15         if (ch[x][1])lazy[ch[x][1]] ^= 1;
    16         swap(ch[x][0], ch[x][1]);
    17         lazy[x] = 0;
    18     }
    19 }
    20 void rotate(int x) {//将x旋转到x的父亲的位置
    21     int y = fa[x];
    22     int z = fa[y];
    23     pushdown(y); pushdown(x);
    24     int k = (ch[y][1] == x);
    25     ch[z][ch[z][1] == y] = x;
    26     fa[x] = z;
    27     ch[y][k] = ch[x][k ^ 1];
    28     fa[ch[x][k ^ 1]] = y;
    29     ch[x][k ^ 1] = y;
    30     fa[y] = x;
    31     pushup(y); pushup(x);
    32 }
    33 void splay(int x, int goal) {//将x旋转为goal的子节点
    34     while (fa[x] != goal) {
    35         int y = fa[x];
    36         int z = fa[y];
    37         if (z != goal)
    38             (ch[y][1] == x) ^ (ch[z][1] == y) ? rotate(x) : rotate(y);
    39         //如果x和y同为左儿子或者右儿子先旋转y
    40         //如果x和y不同为左儿子或者右儿子先旋转x
    41         rotate(x);
    42     }
    43     if (goal == 0)
    44         root = x;
    45 }
    46 int build(int l, int r, int f) {
    47     if (l > r)return 0;
    48     int mid = l + r >> 1, now = ++cnt;
    49     val[now] = a[mid], fa[now] = f, lazy[now] = 0;
    50     ch[now][0] = build(l, mid - 1, now);
    51     ch[now][1] = build(mid + 1, r, now);
    52     pushup(now);
    53     return now;
    54 }
    55 int FindK(int root, int k) {
    56     int now = root;
    57     while (1) {
    58         pushdown(now);
    59         if (k <= siz[ch[now][0]])
    60             now = ch[now][0];
    61         else {
    62             k -= siz[ch[now][0]] + 1;
    63             if (k == 0)return now;
    64             else now = ch[now][1];
    65         }
    66     }
    67 }
    68 void rever(int l, int r) {
    69     int ll = FindK(root, l);
    70     int rr = FindK(root, r + 2);
    71     splay(ll, 0);
    72     splay(rr, ll);
    73     pushdown(root);
    74     lazy[ch[ch[root][1]][0]] ^= 1;
    75 }
    76 void dfs(int x) {
    77     pushdown(x);
    78     if (ch[x][0])dfs(ch[x][0]);
    79     if (val[x] != inf && val[x] != -inf)
    80         printf("%d ", val[x]);
    81     if (ch[x][1])dfs(ch[x][1]);
    82 }
    83 int main() {
    84     int n, m;
    85     scanf("%d%d", &n, &m);
    86     for (int i = 1; i <= n; i++)
    87         a[i + 1] = i;
    88     a[1] = -inf, a[n + 2] = inf;
    89     root = build(1, n + 2, 0);
    90     while (m--) {
    91         int l, r;
    92         scanf("%d%d", &l, &r);
    93         rever(l, r);
    94     }
    95     dfs(root);
    96 }

     无旋treap做法

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn = 1e5 + 10;
     5 int Siz[maxn], ls[maxn], rs[maxn], pos[maxn], lazy[maxn], root;
     6 int cnt;
     7 inline void up(int x) {
     8     Siz[x] = Siz[ls[x]] + Siz[rs[x]] + 1;
     9 }
    10 inline void down(int x) {
    11     if (lazy[x]) {
    12         swap(ls[x], rs[x]);
    13         lazy[ls[x]] ^= 1;
    14         lazy[rs[x]] ^= 1;
    15         lazy[x] = 0;
    16     }
    17 }
    18 void split_size(int x, int siz, int &A, int &B) {
    19     if (x == 0)return (void)(A = B = 0);
    20     down(x);
    21     if (siz <= Siz[ls[x]])
    22         B = x, split_size(ls[x], siz, A, ls[x]);
    23     else
    24         A = x, split_size(rs[x], siz - Siz[ls[x]] - 1, rs[x], B);
    25     up(x);
    26 }
    27 int Merge(int A, int B) {
    28     if (A == 0 || B == 0)return A | B;
    29     int ans;
    30     down(A);
    31     down(B);
    32     if (pos[A] > pos[B])ans = A, rs[A] = Merge(rs[A], B);
    33     else ans = B, ls[B] = Merge(A, ls[B]);
    34     up(ans);
    35     return ans;
    36 }
    37 int build(int l, int r) {
    38     if (l > r)return 0;
    39     int mid = l + r >> 1;
    40     ls[mid] = build(l, mid - 1);
    41     rs[mid] = build(mid + 1, r);
    42     pos[mid] = rand();
    43     up(mid);
    44     return mid;
    45 }
    46 void dfs(int x) {
    47     if (x) {
    48         down(x);
    49         dfs(ls[x]);
    50         printf("%d ", x);
    51         dfs(rs[x]);
    52     }
    53 }
    54 int main() {
    55     int n, m;
    56     scanf("%d%d", &n, &m);
    57     root = build(1, n);
    58     while (m--) {
    59         int l, r;
    60         scanf("%d%d", &l, &r);
    61         int A, B, C, D;
    62         split_size(root, l - 1, A, B);
    63         split_size(B, r - l + 1, C, D);
    64         lazy[C] ^= 1;
    65         root = Merge(A, Merge(C, D));
    66     }
    67     dfs(root);
    68     system("pause");
    69     return 0;
    70 }
  • 相关阅读:
    Delphi XE4 FireMonkey 开发 IOS APP 发布到 AppStore 最后一步.
    Native iOS Control Delphi XE4
    Delphi XE4 iAD Framework 支持.
    using IOS API with Delphi XE4
    GoF23种设计模式之行为型模式之命令模式
    Android青翼蝠王之ContentProvider
    Android白眉鹰王之BroadcastReceiver
    Android倚天剑之Notification之亮剑IOS
    Android紫衫龙王之Activity
    GoF23种设计模式之行为型模式之访问者模式
  • 原文地址:https://www.cnblogs.com/sainsist/p/11160308.html
Copyright © 2011-2022 走看看