码迷,mamicode.com
首页 > 其他好文 > 详细

treap

时间:2018-09-30 22:49:47      阅读:203      评论:0      收藏:0      [点我收藏+]

标签:har   getc   pre   nbsp   开始   put   div   col   mes   

zip//右旋

void zip(int &k)//右旋 
{
    int y=lc(k);
    lc(k)=rc(y);
    rc(y)=k;
    s(y)=s(k);
    upt(k);
    k=y;
}

zap//左旋

void zap(int &k)//左旋 
{
    int y=rc(k);
    rc(k)=lc(y);
    lc(y)=k;
    s(y)=s(k);
    upt(k);
    k=y;
}

insert//插入

  1.终止,添加单点信息

  2.修改size

  3.向下插入(先插后旋)

void Insert(int &k,int &key)//插入 
{
    if(!k)
    {
        k=++nt,v(k)=key,p(k)=rand();//从1开始 
        s(k)=c(k)=1,lc(k)=rc(k)=0;
        return;
    }
    s(k)++;
    if(v(k)==key) c(k)++;
    else 
        if(v(k)>key) 
        {
            Insert(lc(k),key);
            if(p(lc(k))<p(k)) zip(k); 
        } 
        else{
            Insert(rc(k),key);
            if(p(rc(k))<p(k)) zap(k); 
        }
    return;
} 
Delete//删除 
  1.查找到,删除(先旋后删)
  2.修改size
  3.向下查找
void Delete(int &k,int &key)//删除
{
    if(v(k)==key)
    {
        if(c(k)>1) c(k)--,s(k)--;
        else if(!lc(k) or !rc(k)) k=lc(k)+rc(k);
             else if(p(lc(k))<p(rc(k))) zip(k),Delete(k,key);
                     else zap(k),Delete(k,key);
        return;
    }
    s(k)--;
    if(key<v(k)) Delete(lc(k),key);
    else Delete(rc(k),key);
    return;
}

 

queryrank//查询此元素的名次(如有重复元素,返回最高名次) 
int queryrank(int &key)//查询此元素的名次(如有重复元素,返回最高名次) 
{
    int k=rt,re=0;
    while(k)
    {
        if(key==v(k)) return re+s(lc(k))+1;
        else if(key<v(k)) k=lc(k);
             else re+=s(lc(k))+c(k),k=rc(k);
    }
    return re;
}
 
querykth//查询第k小的元素
int querykth(int k)//查询第k小的元素
{
    int x=rt;
    while(x)
    {
        if(k>s(lc(x)) and k<=s(lc(x))+c(x)) return v(x);
        else if(k<=s(lc(x))) x=lc(x);
             else k-=s(lc(x))+c(x),x=rc(x); 
    }
    return v(x);
} 

 

querypre//查询元素的前驱 
int querypre(int &key)//查询元素的前驱 
{
    int x=rt,re=2e9; 
    while(x)
    {
        if(v(x)<key) re=v(x),x=rc(x);
        else x=lc(x);
    }
    return re;
}
querysur//查询元素的后驱 
int querysur(int &key)//查询元素的后驱 
{
    int x=rt,re=2e9; 
    while(x)
    {
        if(v(x)>key) re=v(x),x=lc(x);
        else x=rc(x);
    }
    return re;
} 
#include<iostream>//来个总代码(洛谷3369(https://www.luogu.org/problemnew/show/P3369))
#include<cstdio>
#include<cstdlib>
using namespace std;
void upt(int &k);
void zip(int &k);//右旋 
void zap(int &k);//左旋 
void Insert(int &k,int &key);//插入
void Delete(int &k,int &key);//删除 
int queryrank(int &key);//查询此元素的名次(如有重复元素,返回最高名次)
int querykth(int k);//查询第k小的元素
int querypre(int &key);//查询元素的前驱 
int querysur(int &key);//查询元素的后驱 
void read(int &x);
void write(int x);
struct node{
    int lc,rc,key,priority,size,cnt;
    #define lc(k) a[k].lc
    #define rc(k) a[k].rc
    #define v(k) a[k].key
    #define p(k) a[k].priority
    #define s(k) a[k].size
    #define c(k) a[k].cnt
};
node a[100050];
int nt=0,rt;//附属条件 
int main()
{
    int n;
    read(n);
    int q,s;
    for(int i=1;i<=n;i++)
    {
        read(q),read(s);
        if(q==1) Insert(rt,s);
        if(q==2) Delete(rt,s);
        if(q==3) write(queryrank(s)),putchar(\n);
        if(q==4) write(querykth(s)),putchar(\n);
        if(q==5) write(querypre(s)),putchar(\n);
        if(q==6) write(querysur(s)),putchar(\n);
    }
    return 0;
} 
void upt(int &k) {s(k)=s(lc(k))+s(rc(k))+c(k);}
void zip(int &k)//右旋 
{
    int y=lc(k);
    lc(k)=rc(y);
    rc(y)=k;
    s(y)=s(k);
    upt(k);
    k=y;
}
void zap(int &k)//左旋 
{
    int y=rc(k);
    rc(k)=lc(y);
    lc(y)=k;
    s(y)=s(k);
    upt(k);
    k=y;
}
void Insert(int &k,int &key)//插入 
{
    if(!k)
    {
        k=++nt,v(k)=key,p(k)=rand();//从1开始 
        s(k)=c(k)=1,lc(k)=rc(k)=0;
        return;
    }
    s(k)++;
    if(v(k)==key) c(k)++;
    else 
        if(v(k)>key) 
        {
            Insert(lc(k),key);
            if(p(lc(k))<p(k)) zip(k); 
        } 
        else{
            Insert(rc(k),key);
            if(p(rc(k))<p(k)) zap(k); 
        }
    return;
} 
void Delete(int &k,int &key)//删除
{
    if(v(k)==key)
    {
        if(c(k)>1) c(k)--,s(k)--;
        else if(!lc(k) or !rc(k)) k=lc(k)+rc(k);
             else if(p(lc(k))<p(rc(k))) zip(k),Delete(k,key);
                     else zap(k),Delete(k,key);
        return;
    }
    s(k)--;
    if(key<v(k)) Delete(lc(k),key);
    else Delete(rc(k),key);
    return;
}
int queryrank(int &key)//查询此元素的名次(如有重复元素,返回最高名次) 
{
    int k=rt,re=0;
    while(k)
    {
        if(key==v(k)) return re+s(lc(k))+1;
        else if(key<v(k)) k=lc(k);
             else re+=s(lc(k))+c(k),k=rc(k);
    }
    return re;
}
int querykth(int k)//查询第k小的元素
{
    int x=rt;
    while(x)
    {
        if(k>s(lc(x)) and k<=s(lc(x))+c(x)) return v(x);
        else if(k<=s(lc(x))) x=lc(x);
             else k-=s(lc(x))+c(x),x=rc(x); 
    }
    return v(x);
} 
int querypre(int &key)//查询元素的前驱 
{
    int x=rt,re=2e9; 
    while(x)
    {
        if(v(x)<key) re=v(x),x=rc(x);
        else x=lc(x);
    }
    return re;
}
int querysur(int &key)//查询元素的后驱 
{
    int x=rt,re=2e9; 
    while(x)
    {
        if(v(x)>key) re=v(x),x=lc(x);
        else x=rc(x);
    }
    return re;
}
void read(int &x)
{
    x=0;
    int i=1;
    char c=getchar();
    while(c<0 or c>9)
    {
        if(c==-) i=-1;
        c=getchar();
    }
    while(c>=0 and c<=9)
    {
        x=x*10+c-0;
        c=getchar();
    }
    x*=i;
}
void write(int x)
{
    if(x<0) putchar(-),x*=-1;
    if(x>9) write(x/10);
    putchar(x%10+0);
}

 

treap

标签:har   getc   pre   nbsp   开始   put   div   col   mes   

原文地址:https://www.cnblogs.com/shzyk/p/9733448.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!