POJ 3481

一道 treap 水题

题干如下,有 n 个客户,每个客户有一个优先度,我们需要3个操作

1 X Y 加入ID为 X ,优先度为 Y 的客户

2 提取出优先度最大的客户

3 提取出优先度最小的客户

乍一看 感觉堆可以解决, 但是我们发现 不但需要最大,还需要最小,那么我们便用 treap 解决即可。。

之前尝试用了 hzwer 模板。。A是A掉了。。但是感觉有点显得太长了,另外也想用一下指针,所以自己加上参考搞了个指针版本的。。。Treap 详细解读在下一篇

 

解题思路很简单了。。不断地找最左和最右,一旦根是空的就输出 0 。

 

以下是 AC 代码

 

 

 

#include<cctype>
#include<cstdio>
#include<cstdlib>//poj 万能头文件用不了
using namespace std;
const int maxn = 1e5+5;
inline int read()
{
    int X=0,w=0; char ch=0;
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}

struct Node
{
    Node *ch[2];
    int r,v,id;
    Node(int v,int id):v(v),id(id)
    {
        r=rand();
        ch[0]=ch[1]=NULL;
    }
    int cmp(int x)
    {
        if(x==v) return -1;
        return x<v? 0:1;
    }
};
void rotate(Node* &o,int d)
{
    Node *k = o->ch[d^1];
    o->ch[d^1] = k->ch[d];  k->ch[d] = o;
    o=k;
}
void insert(Node* &o,int v,int id)
{
    if(o==NULL) o=new Node(v,id);
    else
    {
        int d = (v < o->v) ? 0:1;
        insert(o->ch[d],v,id);
        if(o->ch[d]->r > o->r)
            rotate(o,d^1);
    }
}
void del(Node *&o,int v)
{
    int d = o->cmp(v);
    if(d==-1)
    {
        Node *u=o;
        if(o->ch[0] && o->ch[1])
        {
            int d2 = (o->ch[0]->r < o->ch[1]->r) ? 0:1;
            rotate(o,d2);
            del(o->ch[d2],v);
        }
        else
        {
            if(o->ch[0]==NULL) o=o->ch[1];
            else o=o->ch[0];
            delete u;
        }
    }
    else del(o->ch[d],v);
}
int find_max(Node *o)
{
    if(o->ch[1]==NULL)
    {
        printf("%d\n",o->id);
        return o->v;
    }
    return find_max(o->ch[1]);
}
int find_min(Node *o)
{
    if(o->ch[0]==NULL)
    {
        printf("%d\n",o->id);
        return o->v;
    }
    return find_min(o->ch[0]);
}
int main()
{
    int t;
    Node *root = NULL;
    while(true)
    {
        t=read();
        if(t == 0)break;
        else if(t == 1)
        {
            int id=read(), v=read();
            insert(root, v, id);
        }
        else if(t == 2)
        {
            if(root == NULL) {printf("0\n"); continue;}
            int temp = find_max(root);
            del(root, temp);
        }
        else
        {
            if(root == NULL) {printf("0\n"); continue;}
            int temp = find_min(root);
            del(root, temp);
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值