RT,第一次学平衡树,为什么不加11行srand就能过
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+500 , INF = 0x3f3f3f3f;
int n , tot = 0 , root;
struct tree
{
int l=0 , r=0 , size , val , w , cnt; // 左右节点 , 排名 , 值 , 随机权值 , 数量
}t[maxn];
int GetW() //创建随机权值
{
srand(time(0));
return rand();
}
void PushUp(int &p)
{
t[p].size=t[t[p].l].size + t[t[p].r].size + t[p].cnt;
}
void TurnLeft(int &p) //左旋是指根变成 右子树的左孩子
{
int q = t[p].r;
t[p].r=t[q].l; //p点右子树变成右子树的左子树
t[q].l=p; //p点右子树的左子树变成p点
p=q; //交换两点
PushUp(t[p].l) , PushUp(p); //重新计算长度
}
void TurnRight(int &p) //右旋是指根变成左子树的右孩子 ,左子树的右孩子上有占位 就取出来放到当下根的左子树位上
{
int q = t[p].l;
t[p].l=t[q].r;
t[q].r=p;
p=q;
PushUp(t[p].r) , PushUp(p);
}
int Create(int val) //建点
{
t[++tot].val=val;
t[tot].l=t[tot].r=0 , t[tot].w=GetW() , t[tot].size=t[tot].cnt=1;
return tot;
}
void Init() //初始化
{
Create(-INF) , Create(INF);
root = 1;
t[1].r=2;
if (t[1].w < t[2].w) TurnLeft(root);
}
void Insert(int &p , int val) //插入
{
if (p == 0) p = Create(val);
else if (val == t[p].val)t[p].cnt++;
else if (val > t[p].val)
{
Insert(t[p].r , val);
if (t[t[p].r].w > t[p].w)TurnLeft(p);
}
else
{
Insert(t[p].l , val);
if (t[t[p].l].w > t[p].w)TurnRight(p);
}
PushUp(p);
return;
}
void Remove(int &p , int val) //删除
{
if (p == 0)return;
if (val == t[p].val)
{
if (t[p].cnt > 1)t[p].cnt--;
else if (t[p].r || t[p].l)
{
if (!t[p].r || t[t[p].l].w > t[t[p].r].w)
{
TurnRight(p);
Remove(t[p].r , val);
}
else
{
TurnLeft(p);
Remove(t[p].l , val);
}
}
else p = 0;
}
else if (val < t[p].val) Remove(t[p].l , val);
else Remove(t[p].r , val);
PushUp(p);
return;
}
int GetRank(int p , int val)
{
if (!p)return 1;
if (t[p].val == val) return t[t[p].l].size + 1;
if (t[p].val > val) return GetRank(t[p].l , val);
return t[t[p].l].size + t[p].cnt + GetRank(t[p].r , val);
}
int GetNum(int p , int rank)
{
if (!p) return INF;
if (rank <= t[t[p].l].size) return GetNum(t[p].l , rank);
if (rank <= t[t[p].l].size + t[p].cnt) return t[p].val;
return GetNum(t[p].r , rank - t[t[p].l].size - t[p].cnt);
}
int GetPrev(int p , int val)
{
if (!p)return -INF;
if (val <= t[p].val) return GetPrev(t[p].l , val);
return max(t[p].val , GetPrev(t[p].r , val));
}
int GetSuff(int p , int val)
{
if (!p)return INF;
if (val >= t[p].val) return GetSuff(t[p].r , val);
return min(t[p].val , GetSuff(t[p].l , val));
}
int main ()
{
int op , x , ans = 0;
scanf("%d" , &n);
Init();
while(n--)
{
cin >> op >> x;
if(op==1) Insert(root,x);
else if(op == 2) Remove(root,x);
else if(op == 3) ans = GetRank(root,x)-1;
else if(op == 4) ans = GetNum(root,x+1);
else if(op == 5) ans = GetPrev(root, x);
else if(op == 6) ans = GetSuff(root,x);
if (op >= 3) printf("%d\n" , ans);
}
return 0;
}