zoukankan      html  css  js  c++  java
  • Splay

    #include <cstdio>
    #include <iostream>
    using namespace std;
    
    const int N = 1e5+2;
    
    
    struct Splay {
       struct node {
          node *ch[2], *fa; int val, size;
          node (node *fa = NULL, int val = 0) : fa(fa), val(val) {ch[0] = ch[1] = NULL; size = 1;}
          inline bool isr () { return fa -> ch[1] == this;}
          inline bool up () { size = (ch[0] ? ch[0] -> size : 0) + (ch[1] ? ch[1] -> size : 0) + 1;}
          inline int rnk () { return (ch[0] ? ch[0] -> size : 0) + 1;}
       }*root, pool[N], *tail, *st[N];
       int top;
       Splay () { tail = pool; root = NULL; top = 0;}
       inline void rot (node *x) {
          int k = x -> isr();
          node *y = x -> fa, *z = y -> fa, *w = x -> ch[!k];
          if (y == root) root = x; else z -> ch[y->isr()] = x;
          x -> fa = z, y -> fa = x;
          x -> ch[!k] = y, y -> ch[k] = w;
          if (w) w -> fa = y;
          y -> up(); x -> up();
       }
       inline void splay (node *x) {
          while (x != root) {
             if (x -> fa != root) rot (x -> isr() ^ x -> fa -> isr() ? x : x -> fa);
             rot (x);
          }
       }
       inline void Insert (int val) {
          if (!root) return (void) (root = new (tail ++) node (NULL, val));
          node *x = root, *fa = NULL;
          while (x) {
    	 fa = x;
             x = x -> ch[val > x -> val];
          }
          x = new (tail ++) node (fa, val);
          fa -> ch[val > fa -> val] = x; splay (x);
       }
    	
       node *merge (node *x, node *y, node *fa) {
          if (x) x -> fa = fa;
          if (y) y -> fa = fa;
          if (!x || !y) return x ? x : y;
          return x -> ch[1] = merge (x -> ch[1], y, x), x -> up(), x;
       }
    	
       inline void del (int val) {
          node *x = root;
          while (x && x -> val != val) x = x -> ch[val > x -> val];
          if (x == NULL) return;
    	 splay(x); 
    	 root = merge (x -> ch[0], x -> ch[1], NULL);
    	 st[++top] = x, x = NULL;
       }
       inline int rnk (int val) {
          node *x = root, *last = NULL; int res = 0;
          while (x) {
    	 last = x;
    	 if (val <= x -> val) x = x -> ch[0];
    	 else res += x -> rnk(), x = x -> ch[1];
          }
          return splay(last), res + 1;
       }
       inline int kth (int k) {
          node *x = root;
          while (x && x -> rnk() != k) {
             if (x -> rnk() > k) x = x -> ch[0];
    	 else k -= x -> rnk(), x = x -> ch[1];
          }
          return splay (x), x -> val;
       }
       inline int pre (int x) {return kth(rnk(x)-1);}
       inline int nxt (int x) {return kth(rnk(x+1));}
       inline void Action () {
          int t;
          scanf ("%d", &t);
          while (t --> 0) {
             int opt, x;
             scanf ("%d%d", &opt, &x);
    	 if (opt == 1) Insert (x);
    	 if (opt == 2) del (x);
    	 if (opt == 3) printf ("%d
    ", rnk(x)); 
             if (opt == 4) printf ("%d
    ", kth(x));
    	 if (opt == 5) printf ("%d
    ", pre(x));
    	 if (opt == 6) printf ("%d
    ", nxt(x));
          }
       }
    }yhm;
    
    int main () { return yhm.Action(), 0;}
    

    关于Splay的一些操作

    1.$rot $

    (k = x -> isr())

    以及后文一些关于(ch[k])或者(ch[!k])的操作非常巧妙

    回复数据的时候先(y -> up()) 然后再(x -> up())

    因为x是y的爸爸

    2.(splay)

    有双链和单练之分 (防止退化成链)

    ta与ta爹如果在同一个儿子的方向 就转一下ta爹

    如果不在一个方向就转一下ta

    3.关于(del) (rnk) (kth)

    这几个函数写完之后需要记得splay一下

    4.关于(isr) (rnk) (up)几个函数

    inline bool isr () { return fa -> ch[1] == this;}
    
    inline int up () { return siz = (ch[0] ? ch[0] -> siz : 0) + (ch[1] ? ch[1] -> siz : 0) + 1;}
    
    inline int rnk () { return (ch[0] ? ch[0] -> siz : 0) + 1;}
    
  • 相关阅读:
    一本通 1297:公共子序列
    【未完】一本通 1277:【例9.21】方格取数
    一本通 1295:装箱问题
    一本通 1268:【例9.12】完全背包问题
    【BZOJ4416】阶乘字符串(SHOI2013)-状压DP
    【BZOJ2658】小蓝的好友(ZJOI2012)-扫描线+Treap
    【BZOJ2159】Crash的文明世界-第二类斯特林数+树形DP
    【HDU4336】Card Collector-Min-Max容斥
    【BZOJ3997】组合数学(TJOI2015)-Dilworth定理+DP
    【LOJ2537】Minimax(PKUWC2018)-树形DP+线段树合并
  • 原文地址:https://www.cnblogs.com/yszhyhm/p/13365602.html
Copyright © 2011-2022 走看看