P3391 【模板】文艺平衡树
P3369 【模板】普通平衡树
已经测试过上述题目(而且性能较好),可放心食用~~
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
int n;
struct Splay
{
int rt, tot, fa[N], ch[N][2], val[N], cnt[N], sz[N];
//sz[x]:x节点子树的大小;cnt[x]:与x节点权值相同的数的个数;val[x]:x节点的权值
int rev[N];//x节点的左右子树是否需要翻转
inline void init()
{
rt=tot=0;
}
inline void pushup(int x) { sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + cnt[x]; }//更新节点x的sz
inline bool get(int x) { return x == ch[fa[x]][1]; }//x是否是其父亲节点的右儿子
inline void clear(int x) {ch[x][0] = ch[x][1] = fa[x] = val[x] = sz[x] = cnt[x] = 0;}//删除节点x
inline void rotate(int x,int &k)
{
int y=fa[x],z=fa[y],d=ch[y][1]==x;
if (y==k)k=x;//k是x的父亲节点
else ch[z][ch[z][1]==y]=x;
fa[ch[x][d^1]]=y;fa[y]=x;fa[x]=z;
ch[y][d]=ch[x][d^1];ch[x][d^1]=y;
pushup(x);pushup(y);
}
inline void splay(int x,int &k)//把节点x与节点k互换,随时更新k的值,防止把k旋转到x子树里
{
while (x!=k)
{
int y=fa[x],z=fa[y];
if (y!=k)//双旋操作
{
if ((ch[z][0]==y)^(ch[y][0]==x))rotate(x,k);