二叉搜索树之:【BST+heap==treap】【二叉搜索树与堆的结合】

 

 

本题的题意分析与代码梳理

/*
已知了treap是 二叉搜索树和 堆的结合,
那去掉了 堆就是二叉搜索树了
去掉堆,意味着去掉 zag,zig,和val

下面是 treap这个结合体的代码
*/
#include <bits/stdc++.h> 
using namespace std;
const int N=1010;
const int mode=1e9+7,INF=1e8;
typedef long long LL;
int n; 
int C[N][N];
int a[N];

struct Node
{
    int l,r;
    int key,val;
    int siz;
}tr[N];

int root,idx;


void pushup(int p)
{
    tr[p].siz=tr[tr[p].l].siz+tr[tr[p].r].siz+1;
} 

void zig(int &p)
{
    int q=tr[p].l;
    tr[p].l=tr[q].r;
    tr[q].r=p;
    p=q;

    pushup(p),pushup(tr[p].r);
}

void zag(int &p)
{
    int q=tr[p].r;
    tr[p].r=tr[q].l;
    tr[q].l=p;
    p=q;

    pushup(p),pushup(tr[p].l);
}

void init()
{
  for(int a=0;a<N;a++)  
  for(int b=0;b<=a;b++)
  {
    if(b==0)  C[a][b]=1;
    else C[a][b]=(C[a-1][b-1]+C[a-1][b])%mode; 
  }
} 

int get_node(int key)
{
    tr[++idx].key=key;
    tr[idx].siz=1;
    //tr[idx].val=rand();
    return idx; 
}
void build()
{
    get_node(-INF),get_node(INF);
    root=1,tr[1].r=2;
    pushup(root);

//  if(tr[1].val<tr[2].val)
//  {
        zag(root);
    //}
}

void insert(int &p,int key)
{
    if(!p)
    {
        p=get_node(key);
    }
    else if(key<tr[p].key)
    {
        insert(tr[p].l,key);
        //if (tr[tr[p].l].val > tr[p].val)
        //zig(p);
    } 
    else if(key>tr[p].key)
    {
        insert(tr[p].r,key);
        //if (tr[tr[p].r].val > tr[p].val)
        //zag(p);
    } 
    else if(key==tr[p].key)
    {
        return;
    } 

    pushup(p);
}

int dfs(int p)
{
    if(!p)  return 1;

    LL l=dfs(tr[p].l);
    LL r=dfs(tr[p].r);

    int lson=tr[p].l,rson=tr[p].r;
    int lnum=tr[lson].siz,rnum=tr[rson].siz;

    return l*r%mode*C[lnum+rnum][lnum]%mode;
}
int main()
{
    init();
    while(cin>>n)
    {
        idx=0;
        for(int i=1;i<N;i++)  //一开始没有正确结果就在于这里,没有设置为0 
        {
            tr[i].l=tr[i].r=tr[i].key=tr[i].val=tr[i].siz=0;
        } 

        build();

        for(int i=1;i<=n;i++ )  cin>>a[i];

        for(int i=1;i<=n;i++)
        {
            insert(root,a[i]);
        }

        cout<<dfs(root)<<endl;
    } 
} 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值