hdoj 5249 KPI(treap)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5249

思路分析:使用queue记录管道中的值并使用treap能够查询第K大的功能查询第floor(m/2)+1大的数值;

对于in value操作,将value插入queue中和treap中;对于out操作,在treap中删除queue中队头元素,并在queue中使队头元素出队;

对于query操作,因为tail – head的值即为管道中的值的个数,使用treap查询第floor((tail – head) / 2) + 1大的元素即可;

代码如下:

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

const int MAX_N = 10000 + 100;
int queue[MAX_N];

struct Node{
    Node *ch[2];
    int value, key;
    int size;
    int cmp(int x) const{
        if (x == value) return -1;
        return x < value ? 0 : 1;
    }
    void Maintain(){
        size = 1;
        if (ch[0] != NULL) size += ch[0]->size;
        if (ch[1] != NULL) size += ch[1]->size;
    }
};

void Rotate(Node *&o, int d){
    Node *k = o->ch[d ^ 1];
    o->ch[d ^ 1] = k->ch[d];
    k->ch[d] = o;
    o->Maintain();
    k->Maintain();
    o = k;
}

void Insert(Node *&o, int x){
    if (o == NULL){
        o = new Node();
        o->ch[0] = o->ch[1] = NULL;
        o->value = x;
        o->key = rand();
    }
    else{
        int d = (x < (o->value) ? 0 : 1);
        Insert(o->ch[d], x);
        if (o->ch[d]->key > o->key)
            Rotate(o, d ^ 1);
    }
    o->Maintain();
}

void Remove(Node *&o, int x){
    int d = o->cmp(x);

    if (d == -1){
        Node *u = o;

        if (o->ch[0] != NULL && o->ch[1] != NULL){
            int d2 = (o->ch[0]->key > o->ch[1]->key ? 1 : 0);

            Rotate(o, d2);
            Remove(o->ch[d2], x);
        }else{
            if (o->ch[0] == NULL)
                o = o->ch[1];
            else
                o = o->ch[0];
            delete u;
        }
    }else
        Remove(o->ch[d], x);
    if (o != NULL)
        o->Maintain( );
}

int Find(Node *o, int x){
    while (o != NULL){
        int d = o->cmp(x);

        if (d == -1) return 1;
        else o = o->ch[d];
    }
    return 0;
}

int FindKth(Node *o, int k){
    int l_size = (o->ch[0] == NULL ? 0 : o->ch[0]->size);
    if (k == l_size + 1)
        return o->value;
    else if (k <= l_size)
        return FindKth(o->ch[0], k);
    else
        return FindKth(o->ch[1], k - l_size - 1);
}

void MakeEmpty(Node *root){
    if (root == NULL)
        return;
    if (root->ch[0])
        MakeEmpty(root->ch[0]);
    if (root->ch[1])
        MakeEmpty(root->ch[1]);
    delete root;
}

int main(){
    int n, case_id = 0, value;

    srand(100);
    while (scanf("%d", &n) != EOF){
        Node *root = NULL;
        int head = 0, tail = 0, ans;
        char str[10];

        printf("Case #%d:
", ++case_id);
        for (int i = 0; i < n; ++i){
            scanf("%s", str);
            if (str[0] == 'i'){
                scanf("%d", &value);
                queue[tail++] = value;
                Insert(root, value);
            }
            else if (str[0] == 'o')
                Remove(root, queue[head++]);
            else{
                ans = FindKth(root, (tail - head) / 2 + 1);
                printf("%d
", ans);
            }
        }
        MakeEmpty(root);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/tallisHe/p/4584287.html