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;}
原文地址:https://www.cnblogs.com/yszhyhm/p/13365602.html