贴几篇网上找的splay入门博客
https://www.cnblogs.com/cjyyb/p/7499020.html
https://www.cnblogs.com/santiego/p/10011592.html
D HDU 4680
模板题,参考了网上的treap模板(我不会写啊)
#include<cstdio> #include<algorithm> #define maxn 100010 #define inf 200000000 using namespace std; struct node { int siz,num,va,pri; }e[maxn]; int son[maxn][2],cnt=0,rt=0; void pushup(int k) { e[k].siz=e[son[k][0]].siz+e[son[k][1]].siz+e[k].num; } void rotate(int &p,int d)//0左旋1右旋 { int k=son[p][d^1];//k为p的d^1儿子 son[p][d^1]=son[k][d]; son[k][d]=p;//k的d儿子变为p pushup(p); pushup(k); p=k; } void ins(int &p,int x)//k为当前节点,x为要插入的数字 { if (!p)//空节点 { p=++cnt;//赋予节点编号 e[p].siz=1; e[p].num=1; e[p].va=x; e[p].pri=rand(); return; } if (e[p].va==x) { e[p].siz++; e[p].num++; return; } int d; if (x>e[p].va) d=1; else d=0; ins(son[p][d],x); if (e[p].pri<e[son[p][d]].pri) rotate(p,d^1);//维护pri大根堆 pushup(p); } void del(int &p,int x) { if (!p) return; if (x<e[p].va) del(son[p][0],x); else if (x>e[p].va) del(son[p][1],x); else { if (!son[p][0] && !son[p][1])//叶子节点,直接删除 { e[p].num--; e[p].siz--; if (e[p].num==0) p=0; } else if (son[p][0] && !son[p][1])//只有一个儿子的情况,把儿子转上来,到子树里解决 { rotate(p,1); del(son[p][1],x); } else if (!son[p][0] && son[p][1]) { rotate(p,0); del(son[p][0],x); } else if (son[p][0] && son[p][1])//把较大的儿子转上来,去另一个子树里解决 { int d; if (e[son[p][0]].pri>e[son[p][1]].pri) d=1; else d=0; rotate(p,d); del(son[p][d],x); } } pushup(p); } int rk(int p,int x) { if (!p) return 0; if (e[p].va==x) return e[son[p][0]].siz+1; if (e[p].va>x) return rk(son[p][0],x); //x在左子树中 if (e[p].va<x) return e[son[p][0]].siz+e[p].num+rk(son[p][1],x); //x在右子树中,排名先加上左子树大小和当前位置次数 } int find(int p,int x) { if (!p) return 0; if (e[son[p][0]].siz>=x) return find(son[p][0],x); //rk小于左子树大小,去左子树中找答案 else if (e[son[p][0]].siz+e[p].num<x) return find(son[p][1],x-e[son[p][0]].siz-e[p].num); //rk大于左子树大小和当前位置次数的和,去右子树中找答案 else return e[p].va; } int pre(int p,int x) { if (!p) return -inf; if (e[p].va>=x) return pre(son[p][0],x); //当前值大于等于x,去左子树里找先驱 else return max(e[p].va,pre(son[p][1],x)); //当前值小于x,去右子树里找先驱,并与当前值比较得出答案 } int suc(int p,int x) { if (!p) return inf; if (e[p].va<=x) return suc(son[p][1],x); else return min(e[p].va,suc(son[p][0],x)); } int main() { int n,op,x; scanf("%d",&n); while (n--) { scanf("%d%d",&op,&x); if (op==1) ins(rt,x); else if (op==2) del(rt,x); else if (op==3) printf("%d ",rk(rt,x)); else if (op==4) printf("%d ",find(rt,x)); else if (op==5) printf("%d ",pre(rt,x)); else if (op==6) printf("%d ",suc(rt,x)); } return 0; }