poj3481——treap

题意:动态求一个集合的最大值和最小值。

treap的模板题。

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

struct node
{
    node * ch[2];
    int r, v, q;
    bool operator < (const node & rhs) const { return r < rhs.r; }

    int cmp(int x) const
    {
        if(x == v) return -1;
        return x < v ? 0 : 1;
    }
};

node * root;

void rotate(node * & o, int d) // d = 0 左旋 d = 1 右旋
{
    node * k = o->ch[d ^ 1]; o->ch[d ^ 1] = k->ch[d]; k->ch[d] = o; o = k;
}

void insert(node * & o, int x, int q)
{
    if(o == NULL) { o = new node(); o->ch[0] = o->ch[1] = NULL; o->v = x; o->r = rand(); o->q = q; }
    else
    {
        int d = o->cmp(x);
        insert(o->ch[d], x, q);
        if(o->ch[d] > o) rotate(o, d ^ 1);
    }
}

void remove(node * & o, int x)
{
    int d = o->cmp(x);
    if(d == -1)
    {
        if(o->ch[0] == NULL) { o = o->ch[1]; }
        else if(o ->ch[1] == NULL) { o = o->ch[0]; }
        else
        {
            int d2 = (o->ch[0] > o->ch[1]) ? 1 : 0;
            rotate(o, d2); remove(o->ch[d2], x);
        }
    }
    else remove(o->ch[d], x);
}

int findmax(node * & o)
{
    if(o->ch[1] == NULL) { int q = o->q; remove(o, o->v); return q; }
    else return findmax(o->ch[1]);
}

int findmin(node * & o)
{
    if(o->ch[0] == NULL) { int q = o->q; remove(o, o->v); return q; }
    else return findmin(o->ch[0]);
}

int main()
{
    freopen("in", "r", stdin);
    root = NULL;
    int cas;
    while(~scanf("%d", &cas) && cas != 0)
    {
        if(cas == 1)
        {
            int k, p; scanf("%d %d", &k, &p);
            insert(root, p, k);
        }
        else if(cas == 2)
        {
            if(root == NULL) { printf("0\n"); continue; }
            printf("%d\n", findmax(root));
        }
        else
        {
            if(root == NULL) { printf("0\n"); continue; }
            printf("%d\n", findmin(root));
        }
    }
    return 0;
}

/*
2
1 20 14
1 30 3
2
1 10 99
3
2
2
0

0
20
30
10
0
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值