【SBT】 POJ 3481 Double Queue

点击打开链接

1 表示插入 点

2表示求最大值的点标 并删除

3表示求最小值的点标 并删除

0表示结束

模板题。增加了一个val 表示为输出的值

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#include <queue>
#include <stack>
#include <vector>
#include <list>
#include <deque>
#include <set>
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <map>
typedef long long LL;
const int INF = 0x3f3f3f3f;
const LL mod = 1e9+7;
const int MAXN = 1000050;
struct SBT
{
    int left,right,size,key,val;
    void init()
    {
        left=right=key=0;
        size=1;
    }
}tree[MAXN];
int root,top,delp;
void left_rot(int &x)
{
    int y = tree[x].right;
    tree[x].right = tree[y].left;
    tree[y].left = x;
    tree[y].size = tree[x].size;//原x节点数
    tree[x].size = tree[tree[x].left].size + tree[tree[x].right].size + 1;
    x = y;
}
void right_rot(int &x)
{
    int y = tree[x].left;
    tree[x].left = tree[y].right;
    tree[y].right = x;
    tree[y].size = tree[x].size;
    tree[x].size = tree[tree[x].left].size + tree[tree[x].right].size + 1;
    x = y;
}
void maintain(int &x,bool flag)
{
    if(flag == false)//left
    {
        if(tree[tree[tree[x].left].left].size>tree[tree[x].right].size)
            right_rot(x);
        else if(tree[tree[tree[x].left].right].size>tree[tree[x].right].size)
        {
            left_rot(tree[x].left);
            right_rot(x);
        }
        else return ;
    }
    else
    {
        if(tree[tree[tree[x].right].right].size > tree[tree[x].left].size)
            left_rot(x);
        else if(tree[tree[tree[x].right].left].size > tree[tree[x].left].size)
        {
            right_rot(tree[x].right);
            left_rot(x);
        }
        else return ;
    }
    maintain(tree[x].left,false);
    maintain(tree[x].right,true);
    maintain(x,true);
    maintain(x,false);
}
/*
*insert没有合并相同的元素,如果出现相同的元素则把它放到右子树上,这样能保证求第k小数的时候对相同元素也能正确
*/
void insert(int &x,int key,int val)
{
    if(x == 0)
    {
        x = ++top;
        tree[x].left =tree[x].right = 0;
        tree[x].size = 1;
        tree[x].key = key;
        tree[x].val = val;
    }
    else
    {
        tree[x].size ++;
        if(key < tree[x].key) insert(tree[x].left,key,val);
        else insert(tree[x].right,key,val);
        maintain(x,key>=tree[x].key);
    }
}
int del(int &p,int w)
{
    if(tree[p].key==w || (tree[p].left==0 && w<tree[p].key) || (tree[p].right==0 &&w>tree[p].key))
    {
        int delnum=tree[p].key;
        if(tree[p].left==0 ||tree[p].right==0)
            p=tree[p].left+tree[p].right;
        else tree[p].key=del(tree[p].left,INF);
        return delnum;
    }
    if(w<tree[p].key) return del(tree[p].left,w);
    else return del(tree[p].right,w);
}

int remove(int &x,int key)
{
    int d_key;
    //if(!x) return 0;
    tree[x].size --;
    if((key == tree[x].key)||(key < tree[x].key && tree[x].left == 0) ||(key>tree[x].key && tree[x].right == 0))
    {
        d_key = tree[x].key;
        if(tree[x].left && tree[x].right)
        {
            tree[x].key = remove(tree[x].left,tree[x].key+1);
        }
        else
        {
            x = tree[x].left + tree[x].right;
        }
    }
    else if(key > tree[x].key)
        d_key = remove(tree[x].right,key);
    else if(key < tree[x].key)
        d_key = remove(tree[x].left,key);
    return d_key;
}
int getmin()
{
    int x;
    for(x=root;tree[x].left;x=tree[x].left);
    delp=tree[x].key;
    return tree[x].val;
}
int getmax()
{
    int x;
    for(x=root;tree[x].right;x=tree[x].right);
    delp=tree[x].key;
    return tree[x].val;
}
int select(int &x,int k)
{
    int r = tree[tree[x].left].size +1;
    if(r == k) return tree[x].key;
    else if(r < k ) return select(tree[x].right,k-r);
    else return select(tree[x].left,k);
}
int rank(int &x,int key)//key 排第几
{
    if(key<tree[x].key)
        return rank(tree[x].left,key);
    else if(key>tree[x].key)
        return rank(tree[x].right,key) + tree[tree[x].left].size + 1;
    else return tree[tree[x].left].size + 1;
}
int pred(int &x,int y,int key)
{
    if(x==0) return y;
    if(tree[x].key < key)
        return pred(tree[x].right,x,key);
    else return pred(tree[x].left,y,key);
}
int succ(int &x,int y,int key)
{
    if(x == 0) return y;
    if(tree[x].key > key)
        return succ(tree[x].left,x,key);
    else return succ(tree[x].right,y,key);
}
void inorder(int &x)
{
    if(x==0) return;
    else
    {
        inorder(tree[x].left);
        cout<<x<<" "<<tree[x].key<<" "<<" "<<tree[x].size<<" "<<tree[tree[x].left].key<<" "<<tree[tree[x].right].key<<endl;
        inorder(tree[x].right);
    }
}
int main()
{
    int n,a,b;
    root=0,top=0;
    while(scanf("%d",&n),n)
    {
        if(n==1)
        {
            scanf("%d%d",&a,&b);
            insert(root,b,a);
        }
        else if(n==2){
            printf("%d\n",getmax());
            remove(root,delp);
        }
        else
        {
            printf("%d\n",getmin());
            remove(root,delp);
        }
    }
    return 0;
}

=====================================模板==================================================

#define N 1000005  
using namespace std;  
struct SBT{  
    //左子树指针,右子树指针,大小,键值  
    int left,right,size,key;  
    void Init(){  
        left=right=key=0;  
        size=1;  
    }  
}T[N];  
int root,tot; //根的位置以及节点个数  
//左旋转处理  
void Left_rot(int &x){    
    int k=T[x].right;  
    T[x].right=T[k].left;  
    T[k].left=x;  
    T[k].size=T[x].size;  
    T[x].size=T[T[x].left].size+T[T[x].right].size+1;  
    x=k;  
}  
//右旋转处理  
void Right_rot(int &x){  
    int k=T[x].left;  
    T[x].left=T[k].right;  
    T[k].right=x;  
    T[k].size=T[x].size;  
    T[x].size=T[T[x].left].size+T[T[x].right].size+1;  
    x=k;  
}  
//调整处理  
void Maintain(int &r,bool flag){  
    if(flag){  //更新右子树  
        if(T[T[T[r].right].right].size>T[T[r].left].size)  
            Left_rot(r);  
        else if(T[T[T[r].right].left].size>T[T[r].left].size){  
            Right_rot(T[r].right);  
            Left_rot(r);  
        }  
        else  
            return;  
    }   
    else{   //更新在左子树  
        if(T[T[T[r].left].left].size>T[T[r].right].size)  
            Right_rot(r);  
        else if(T[T[T[r].left].right].size>T[T[r].right].size){  
            Left_rot(T[r].left);  
            Right_rot(r);  
        }  
        else   
            return;  
    }  
    //更新子树,然后再更新根,直到平衡为止  
    Maintain(T[r].left,false);  
    Maintain(T[r].right,true);  
    Maintain(r,false);  
    Maintain(r,true);  
}  
//插入新节点  
void Insert(int &r,int k){  
    if(r==0){  
        r=++tot;  
        T[r].Init();  
        T[r].key=k;  
    }  
    else{  
        T[r].size++;  
        if(k<T[r].key)  
            Insert(T[r].left,k);  
        else  
            Insert(T[r].right,k);  
        //插入后要调整,保证平衡  
        Maintain(r,k>=T[r].key);  
    }  
}  
//删除结点,利用的是前驱替换  
int Remove(int &r,int k){  
    int d_key;  
    if(!r)  
        return 0;  
    T[r].size--;  
    //前者说明就是要删的节点,后两者说明不存在此节点  
    if(T[r].key==k||(T[r].left==0&&k<T[r].key)||(T[r].right==0&&k>T[r].key)){  
        d_key=T[r].key;  
        if(T[r].left&&T[r].right)  
            T[r].key=Remove(T[r].left,k+1);  
        else  
            r=T[r].left+T[r].right;  
    }  
    else Remove(k<T[r].key?T[r].left:T[r].right,k);  
}  
//取得最大值,即一直遍历到最右的结点  
int Get_Max(int r){  
    while(T[r].right)  
        r=T[r].right;  
    return r;  
}  
//取得最小值,即一直遍历到最左的结点  
int Get_Min(int r){  
    while(T[r].left)  
        r=T[r].left;  
    return r;  
}  
//获得前驱  
int Get_Pre(int &r,int y,int k){  
    if(r==0) return y;  
    if(k>T[r].key)  
        Get_Pre(T[r].right,r,k);  
    else  
        Get_Pre(T[r].left,y,k);  
}  
//获得后继  
int Get_Next(int &r,int y,int k){  
    if(r==0) return y;  
    if(k<T[r].key)  
        Get_Next(T[r].left,r,k);  
    else  
        Get_Next(T[r].right,y,k);  
}  
//取得第K小的数,注:暂不能解决有重复数的  
int Get_Kth(int &r,int k){  
    int t=T[T[r].left].size+1;  
    if(t==k) return T[r].key;  
    if(t<k)  return Get_Kth(T[r].right,k-r);  
    else return Get_Kth(T[r].left,k);  
}  
//获得结点的名次  
int Get_Rank(int &r,int k){  
    if(k<T[r].key)   
        return Get_Rank(T[r].left,k);  
    else if(k>T[r].key)  
        return Get_Rank(T[r].right,k)+T[T[r].left].size+1;  
    else  
        return T[T[r].left].size+1;  
}  
//排序  
void Inorder(int &r){  
    if(r==0) return;  
    Inorder(T[r].left);  
    printf("%d\n",T[r].key);  
    Inorder(T[r].right);  
}  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值