Treap模板(中级版)

支持:
插入
删除
查找
最大值
最小值
尺寸记录
(支持重复元素)

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<queue>
#include<vector>
#include<climits>
#include<string>
#include<cstdlib>
#include<set>
#include<stack>
#include<map>
#include<bitset>
#include<ctime>
using namespace std;
typedef int ll;
typedef unsigned long long ull;
inline ll read()
{
    char k=0;char ls;ls=getchar();for(;ls<'0'||ls>'9';k=ls,ls=getchar());
    ll x=0;for(;ls>='0'&&ls<='9';ls=getchar())x=x*10+ls-'0';
    if(k=='-')x=0-x;return x;
}
struct E{
    ll lc,rc;//左右孩子
    ll s,sum;//权值和随机数 
    ll fa;//父亲 
    ll size;//子节点大小 
    ll js;//该节点元素计数 
}t[1000050];
ll w;
ll size;
ll root;

inline ll find(ll s)//查找 
{
    if(size==0)
    return 0;
    ll now=root;
    while(now)
    {
        if(t[now].s==s)
        return now;
        if(s<t[now].s)
        {
            now=t[now].lc;
            continue;
        }
        if(s>t[now].s)
        {
            now=t[now].rc;
            continue;
        }
    }
    return 0;
}

ll maxn()//最大值 
{
    ll now=root;
    while(1)
    {
        if(t[now].rc==0)
        return now;
        now=t[now].rc;
    }
}

ll minn()//最小值 
{
    ll now=root;
    while(1)
    {
        if(t[now].lc==0)
        return now;
        now=t[now].lc;
    }
}

void update(ll x)//更新平衡树尺寸
{
    ll now=root;
    while(1)
    {
        --t[now].size;
        if(now==x)return;
        if(t[x].s<t[now].s)
        {
            now=t[now].lc;
            continue;
        }
        if(t[x].s>t[now].s)
        {
            now=t[now].rc;
            continue;
        }
    }
    return;
}

void zig(ll x)//左旋 
{
    t[t[x].fa].size-=t[t[x].rc].size; 
    t[t[x].fa].size-=t[x].js;
    t[x].size+=t[t[t[x].fa].lc].size;
    t[x].size+=t[t[x].fa].js;
    if(root==t[x].fa)
    root=x;
    ll ff=t[t[x].fa].fa;
    t[t[x].fa].fa=x;
    if(ff!=0)
    {
        if(t[ff].lc==t[x].fa)
        t[ff].lc=x;
        if(t[ff].rc==t[x].fa)
        t[ff].rc=x;
    }
    if(t[x].lc!=0)
    t[t[x].lc].fa=t[x].fa;
    t[t[x].fa].rc=t[x].lc;
    t[x].lc=t[x].fa;
    t[x].fa=ff;
    return;
}

void zag(ll x)//右旋 
{
    t[t[x].fa].size-=t[t[x].lc].size; 
    t[t[x].fa].size-=t[x].js;
    t[x].size+=t[t[t[x].fa].rc].size;
    t[x].size+=t[t[x].fa].js;
    if(root==t[x].fa)
    root=x;
    ll ff=t[t[x].fa].fa;
    t[t[x].fa].fa=x;
    if(ff!=0)
    {
        if(t[ff].lc==t[x].fa)
        t[ff].lc=x;
        if(t[ff].rc==t[x].fa)
        t[ff].rc=x;
    }
    if(t[x].rc!=0)
    t[t[x].rc].fa=t[x].fa;
    t[t[x].fa].lc=t[x].rc;
    t[x].rc=t[x].fa;
    t[x].fa=ff;
    return;
}

void strike_off(ll x)//删除指定下标 
{
    while(t[x].lc!=0||t[x].rc!=0)
    {
        if(t[x].lc!=0&&t[x].rc==0)
        {zag(t[x].lc);continue;}

        if(t[x].rc!=0&&t[x].lc==0)
        {zig(t[x].rc);continue;}

        if(t[x].lc!=0&&t[x].rc!=0)
        {
            if(t[t[x].lc].sum<t[t[x].rc].sum)
            zag(t[x].lc);
            else
            zig(t[x].rc);
        }
    }
    update(x);
    if(t[x].fa!=0)
    {
        if(t[t[x].fa].lc==x)
        t[t[x].fa].lc=0;
        if(t[t[x].fa].rc==x)
        t[t[x].fa].rc=0;
    }
    --size;
    if(size==0)
    root=0;
    return;
}

void delete_(ll s)//删除指定数字
{
    ll x=find(s);
    if(x==0)
    return;
    if(t[x].js>1)
    {
        --t[x].js;
        --size;
        update(x);
        return;
    }
    else
    strike_off(x);
    return;
}

void insert(ll s)//插入 
{
    ++size;
    t[++w].s=s;
    t[w].sum=rand()%1000050;
    t[w].size=1;
    t[w].js=1;
    if(size==1)
    {
        root=w;
        return;
    }
    ll pre=root;
    ll now=root;
    while(now!=0)
    {
        if(s==t[now].s)
        {
            ++t[now].size;
            ++t[now].js;
            --w;
            return;
        }
        if(s<t[now].s)
        {
            ++t[now].size;
            pre=now;
            now=t[now].lc;
            continue;
        }
        if(s>t[now].s)
        {
            ++t[now].size;
            pre=now;
            now=t[now].rc;
            continue;
        }
    }
    if(s<t[pre].s)
    t[pre].lc=w;
    if(s>t[pre].s)
    t[pre].rc=w;
    t[w].fa=pre;

    while(t[w].sum<t[t[w].fa].sum)
    {
        if(t[t[w].fa].lc==w)
        {
            zag(w);
            continue;
        }
        if(t[t[w].fa].rc==w)
        {
            zig(w);
            continue;
        }
    }
    return;
}

int main()
{
    srand(19981017);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值