Double Queue平衡树

B - Double Queue
Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u
Submit Status

Description

The new founded Balkan Investment Group Bank (BIG-Bank) opened a new office in Bucharest, equipped with a modern computing environment provided by IBM Romania, and using modern information technologies. As usual, each client of the bank is identified by a positive integer K and, upon arriving to the bank for some services, he or she receives a positive integer priority P. One of the inventions of the young managers of the bank shocked the software engineer of the serving system. They proposed to break the tradition by sometimes calling the serving desk with the lowest priority instead of that with the highest priority. Thus, the system will receive the following types of request:

0 The system needs to stop serving
KP Add client K to the waiting list with priority P
2 Serve the client with the highest priority and drop him or her from the waiting list
3 Serve the client with the lowest priority and drop him or her from the waiting list

Your task is to help the software engineer of the bank by writing a program to implement the requested serving policy.

Input

Each line of the input contains one of the possible requests; only the last line contains the stop-request (code 0). You may assume that when there is a request to include a new client in the list (code 1), there is no other request in the list of the same client or with the same priority. An identifier K is always less than 106, and a priority P is less than 107. The client may arrive for being served multiple times, and each time may obtain a different priority.

Output

For each request with code 2 or 3, the program has to print, in a separate line of the standard output, the identifier of the served client. If the request arrives when the waiting list is empty, then the program prints zero (0) to the output.

Sample Input

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

Sample Output

0
20
30
10
0
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include<iostream>
using namespace std;
const int MAXN = 100005;
const int MOD = 2147483647;

struct Node
{
     int left;      
     int right;     
     int size;      
     int val;       
     int key;       
     int i;//编号 
}tree[MAXN];

int root,tot;

int add(int val,int i){
    tot++;
    tree[tot].size = 1;
    tree[tot].val = val;
    tree[tot].key = rand()%MOD;
    tree[tot].left = 0;
    tree[tot].right = 0;
    tree[tot].i =i;
    return tot;
}

void update_root(int now){
    int left,right;

    left = tree[now].left;
    right = tree[now].right;

    tree[now].size = tree[left].size + tree[right].size + 1;
}

//拆分(now原treap,a左子树,b右子树,val值)
void split_new(int now, int &a, int &b, int val){
    
    if(now == 0){
        a = 0;
        b = 0;
        return;
    }

    if(tree[now].val <= val){//now左子树中的所有值都小于now,
        a = now;
        split_new(tree[now].right, tree[a].right, b, val);
    }else{
        b = now;
        split_new(tree[now].left, a, tree[b].left, val);
    }

    update_root(now);
}//按权值aplit 

void merge_new(int &now, int a, int b){
    
    if(a==0 || b==0){
        now = a+b;
        return;
    }//某节点为空直接返回另一节点,合并结束 

    //按照key值合并(堆性质)
    if(tree[a].key<tree[b].key){
        /**
         * a树key值小于b树,那么b树属于a树的后代,因为b树恒大于a树,那么b树一定属于a树的右后代,
         * a的左子树不变,直接赋给now,递归合并a的右子树和b
         */
        now = a;
        merge_new(tree[now].right, tree[a].right, b);//b加到a的右后代上,a的右子树与y合并 
         
    }else{
        //a的key值大于b树,b的左子树与a合并 
        now = b;
        merge_new(tree[now].left, a, tree[b].left);
    }

    update_root(now);
}

int find_new(int now, int rank){//找第k大
    while (tree[tree[now].left].size+1 != rank){
        if(tree[tree[now].left].size >= rank){
            now = tree[now].left;
        }else{
            rank -= tree[tree[now].left].size + 1;
            now = tree[now].right;
        }
    }
    printf("%d\n", tree[now].i);
    return tree[now].val;
}

void insert_new(int val,int i){
    int x,y,z;

    x = 0;
    y = 0;
    z = add(val,i);
    split_new(root, x, y, val);
    merge_new(x,x,z);
    merge_new(root, x, y);
}

void del_new(int val){
    int x,y,z;

    x = y = z = 0;
    split_new(root, x, y, val);
    split_new(x, x, z, val-1);
    merge_new(z, tree[z].left, tree[z].right);
    merge_new(x, x, z);
    merge_new(root, x, y);
}

void get_rank(int val){
    int x,y;

    x = y = 0;
    split_new(root, x, y, val-1);
    printf("%d\n", tree[x].size+1);
    merge_new(root,x,y);
}

int get_val(int rank){
    return find_new(root, rank);
}

//void get_pre(int val){
//    int x,y;
//
//    x = y = 0;
//    split_new(root, x, y, val-1);
//    find_new(x, tree[x].size);
//    merge_new(root, x, y);
//}
//
//void get_next(int val){
//    int x,y;
//
//    x = y = 0;
//    split_new(root,x,y,val);
//    find_new(y,1);
//    merge_new(root,x,y);
//}

void solve(){
    int n,op,x,i,o,w;
    
    memset(tree, 0, sizeof(tree));
    add(MOD,0);

    root = 1;
    tree[root].size = 0;
    int num=0;
    while(~scanf("%d",&op)&&op!=0){
        switch (op){
            case 1:
                scanf("%d%d",&i,&x);
                //cout<<"**"<<endl; 
                insert_new(x,i);
                num++;
                break;
            case 2:
                if(num==0){
                    printf("0\n");
                    continue;
                }
                o=get_val(num);//查询排名为x的数
                num--;
                del_new(o);//删除x数(若有多个相同的数,则只删除一个)
                break;
            case 3:
                if(num==0){
                    printf("0\n");
                    continue;
                }
                w=get_val(1);//查询排名为x的数
                num--;
                del_new(w);//删除x数(若有多个相同的数,则只删除一个)
                break;    
        }
    }
}

int main(){
    
    solve();
    return 0;
}

 

posted @ 2022-07-30 16:08  killjoyskr  阅读(34)  评论(0)    收藏  举报