int ch[N][2]; //记录左右儿子,0左,1右
int val[N]; //节点的权重
int counts[N]; //重复值的个数
int r[N]; //随机值
int size[N]; //代表下边节点的个数,包括自己
int tot,root; //总共结点的个数; 根节点
int Newnode(int &rt,int v) //添加新节点
{
rt = ++tot;
val[rt] = v;
ch[rt][0] = ch[rt][1] = 0;
counts[rt] = size[rt] = 1;
r[rt] = rand(); //随机值
return rt;
}
inline void PushUp(int rt) //更新以rt为根的节点个数
{
size[rt] = size[ch[rt][0]]+size[ch[rt][1]]+counts[rt]; //左儿子+右儿子+当前rt的重复个数
}
void Rotate(int &x,int kind) //为了维持最小(大)堆(节点的随机值)旋转
{
int y = ch[x][kind^1];
ch[x][kind^1] = ch[y][kind];
ch[y][kind] = x;
PushUp(x);
PushUp(y);
x = y;
}
int Insert(int &rt,int v) //插入
{
if(rt == 0)
return Newnode(rt,v);
int ans;
if(v == val[rt])
counts[rt] ++, ans = rt;
else
{
int kind = (v > val[rt]);
ans = Insert(ch[rt][kind], v);
if(r[ch[rt][kind]] < r[rt])
Rotate(rt, kind^1);
}
PushUp(rt);
return ans;
}
int select(int rt,int k) //查询第k小值
{
if(size[ch[rt][0]] >= k) return select(ch[rt][0],k); //在左子树
if(size[ch[rt][0]]+counts[rt] >= k) return val[rt]; //在当前结点
return select(ch[rt][1],k-size[ch[rt][0]] - counts[rt]); //在右子树
}
void remove(int &rt, int v) //删除,旋转到叶子节点
{
if(val[rt] == v)
{
if(counts[rt] > 1) //个数大于1
counts[rt] --;
else if(!ch[rt][0] && !ch[rt][1]) //是叶子结点
{
rt = 0;
return;
}
else
{
int kind=r[ch[rt][0]] < r[ch[rt][1]];
Rotate(rt,kind);
remove(rt,v);
}
}
else remove(ch[rt][v > val[rt]],v);
PushUp(rt);
}
void Init()
{
ch[0][0] = ch[0][1] = 0;
size[0] = counts[0] = val[0] = 0;
tot = root = 0;
r[0] = (1LL<<31)-1;
Newnode(root,2000000001);
}
Treap 模板
最新推荐文章于 2022-07-14 11:40:17 发布