poj3481 Double Queue(treap)

题面在这里
(vjudge怎么这么不靠谱啊。。以后还是直接用poj算了)
(注册了一个号写了一道题Submissions:14===)

呐,进入正题。

题意:

三个操作:
1. 插入一个编号为x,优先级为y的人
2. 返回优先级最高的人的编号
3. 返回优先级最低的人的编号

做法:

treap模板。(这题我好像也写过splay

大致的想法就是,tree+heap,对于每一个节点维护一个数值,一个优先级,对于数值保持二叉搜索树,对于优先级保持一个堆(大根堆小根堆都可以)。优先级是人为规定的,一般用随机数,这样靠随机性保证复杂度是log的。
然后你会发现treap比splay好写多了QAQ。尤其是旋转。

代码里有注释。

然后说一下为什么提交这么多次。。因为原来写了一个srand(time(NULL)),然后poj就疯狂爆re= =

代码:

/*************************************************************
    Problem: poj 3481 Double Queue
    User: fengyuan
    Language: C++
    Result: Accepted
    Time: 422MS
    Memory: 2276K
    Submit_Time: 2018-01-01 15:49:33
*************************************************************/

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<cstdlib>
using namespace std;

const int N = 100010;
int tot = 0, rt = 0;
struct Treap{
    int id, key, p, ch[2];//p是优先级,保持优先级为一个大根堆
    void set(int x, int y, int z) {
        key = x; id = y; p = z;
        ch[0] = ch[1] = 0;
    }
}T[N];

inline void rot(int &x, int p)//哇treap的旋转比splay好写一万倍啊!!
{
    //p=1表示向左旋,右儿子变成根
    //p=0表示向右旋,左儿子变成根
    int y = T[x].ch[p];
    T[x].ch[p] = T[y].ch[p^1];
    T[y].ch[p^1] = x; x = y;
}
inline void insert(int &rt, int key, int id)
{
    if(!rt) T[rt = ++ tot].set(key, id, rand());//依靠随机化实现深度为log
    else {
        int p = key >= T[rt].key;//p=1代表向右插入,p=0代表向左插入
        insert(T[rt].ch[p], key, id);
        if(T[rt].p < T[T[rt].ch[p]].p) rot(rt, p);//如果优先级不对就旋转,保持平衡
    }
}
inline void del(int &rt, int key)
{
    if(T[rt].key == key) {
        if(T[rt].ch[0] && T[rt].ch[1]) {
            int p = T[T[rt].ch[0]].p < T[T[rt].ch[1]].p;
            rot(rt, p); del(T[rt].ch[p^1], key);//把rt这个节点一直旋到底
        } else {
            int t = rt;
            if(T[rt].ch[0]) rt = T[rt].ch[0]; else rt = T[rt].ch[1]; T[t].set(0, 0, 0);
        }
    } else del(T[rt].ch[key >= T[rt].key], key);
}
inline int get(int rt, int p)//p=1表示查找最大值,p=0表示查找最小值 
{
    while(T[rt].ch[p]) rt = T[rt].ch[p];
    return rt;//返回节点标号
}
int main()
{
    int opt, x, y, all = 0;
    while(~scanf("%d", &opt) && opt) {
        if(opt == 1) {
            scanf("%d%d", &x, &y);
            insert(rt, y, x);
            all ++;
        } else if(opt == 2) {
            if(!all) { puts("0"); continue; }
            x = get(rt, 1);
            printf("%d\n", T[x].id);
            del(rt, T[x].key);
            all --;
        } else {
            if(!all) { puts("0"); continue; }
            x = get(rt, 0);
            printf("%d\n", T[x].id);
            del(rt, T[x].key);
            all --;
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值