无旋streap树(模板)

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3224

blibli学习视频链接:https://www.bilibili.com/video/av46204315/?p=2  感谢大佬,虽然我还是不知道Split和Merge的原理(滑稽)

我知道它们一个可以拆树,一个可以合树。知道一些性质,然后就莫得咯。(也许这就是所谓的不求甚解吧,emmm(自我安慰,实在看不懂原理),略懂就行了,不重要了!)。

无旋streap模板:

#include<algorithm>
#include<string.h>
#include<stdio.h>
#define ls(x) A[x].child[0]
#define rs(x) A[x].child[1]
using namespace std;
struct node
{
    int child[2],Size,v,key;
} A[100010];
int tot;
inline int rand()
{
    static int seed=233;
    return seed = int(seed * 482711ll % 2147483647);
}
inline void up(int r)
{
    A[r].Size=A[ls(r)].Size+A[rs(r)].Size+1;
    return ;
}
void Split(int r,int& x,int& y,int k)
{
    if(!r)
    {
        x=y=0;
        return ;
    }
    if(A[r].v<=k) x=r,Split(rs(r),rs(x),y,k);
    else y=r,Split(ls(r),x,ls(y),k);
    up(r);
    return ;
}
void Merge(int &r,int x,int y)
{
    if(!x||!y)
    {
        r=x+y;
        return ;
    }
    if(A[x].key<A[y].key) r=x,Merge(rs(r),rs(x),y);
    else r=y,Merge(ls(r),x,ls(y));
    up(r);
    return ;
}
int Insert(int& r,int k)
{
    int x=0,y=0,z=++tot;
    A[z].v=k,A[z].Size=1,A[z].key=rand(),ls(z)=0,rs(z)=0;
    Split(r,x,y,k);
    Merge(x,x,z);
    Merge(r,x,y);
    return 0;
}
int del(int &r,int k)
{
    int x=0,y=0,z=0;
    Split(r,x,y,k);
    Split(x,x,z,k-1);
    Merge(z,ls(z),rs(z));
    Merge(x,x,z);
    Merge(r,x,y);
    return 0;
}
int Rank(int &r,int k)
{
    int x=0,y=0,ans;
    Split(r,x,y,k-1);
    ans=A[x].Size+1;
    Merge(r,x,y);
    return ans;
}
int kth(int r,int k)
{
    if(A[r].Size+1<k) return -1;//不存在
    while(A[ls(r)].Size+1!=k)
    {
        if(A[ls(r)].Size>=k) r=ls(r);
        else k-=(A[ls(r)].Size+1),r=rs(r);
    }
    return A[r].v;
}
int pre(int &r,int k)
{
    int x=0,y=0,ans;
    Split(r,x,y,k-1);
    ans=kth(x,A[x].Size);
    Merge(r,x,y);
    return ans;
}
int sub(int &r,int k)
{
    int x=0,y=0,ans;
    Split(r,x,y,k);
    ans=kth(y,1);
    Merge(r,x,y);
    return ans;
}
int main()
{
    int root=0,t,opt,x;
    tot=0;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&opt,&x);
        if(opt==1) Insert(root,x);
        if(opt==2) del(root,x);
        if(opt==3) printf("%d\n",Rank(root,x));
        if(opt==4) printf("%d\n",kth(root,x));
        if(opt==5) printf("%d\n",pre(root,x));
        if(opt==6) printf("%d\n",sub(root,x));
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值