题目大意:
新成立与罗马尼亚布加勒斯特的巴尔干半岛投资集团银行,装备了由IBM公司支持的现代计算环境以及IT技术。通常每个客户在接受服务时都会得到一个编号K和权限P(K < 10^6, P < 10^7)。但是一名经理创造性的提出可以通过低权限(而非高权限)从服务柜台获得服务,因此他建议软件工程师按照如下规则实现该服务系统:
0表示终止服务系统;
1 K P表示在等待队列里假如一名编号为K优先级为P的客户;
2表示为最高权限客户提供服务,并从等待列表中除去该客户;
3表示为最低权限客户提供服务,并从等待列表中除去该客户;
对于命令2和3需要输出相应的客户编号(等待列表中各个客户编号和优先级互不相同)。
伸展树:
注释代码:
/*
* Problem ID : POJ 3481 Double Queue
* Author : Lirx.t.Una
* Language : C++
* Run Time : 235 ms
* Run Memory : 176 KB
*/
#include <stdio.h>
#include <stdlib.h>
//maximum and minimum priority
//最大和最小的有限权值
#define MAXP 10000000
#define MINP 0
struct Node;
typedef struct Node BNode;
typedef struct Node * PtNode;
typedef struct Node * Tree;
struct Node {//伸展树结点
int k;//客户的服务编号
int p;//客户得到的优先权值
Tree lft;
Tree rht;
};
Tree
splay( Tree tree, int p ) {//伸展
if ( !tree )
return NULL;
BNode node;//用于收取从tree上剪下来的结点
Tree tl;//left tree,node的左分支
Tree tr;//right tree,node的右分支
Tree ttmp;//temporary tree,临时变量,用于旋转
node.lft = NULL;
node.rht = NULL;
tl = &node;
tr = &node;
while (1) {
if ( p == tree->p )//查找成功
break;
if ( p < tree->p ) {//目标小于当前结点
//需向左子树伸展
if ( !tree->lft )//若左子树为空则无法伸展
//因此也就到了极限,可以直接退出循环
break;
if ( p < tree->lft->p ) {//若目标比左子树还小
//则在向左子树伸展之前(即嫁接之前)先做一次
//AVL左旋转,这样可以保证嫁接回来后整个数的
//高度可以降低,可以提高查询速率
//常规的AVL左旋转
ttmp = tree->lft;
tree->lft = ttmp->rht;
ttmp->rht = tree;
tree = ttmp;
if ( !tree->lft )//旋转完成后顶点被更新
//因此新的顶点的左子树可能为空
//若为空则不能再继续向新的左子树伸展
//因此必须跳出循环,将剪去的嫁接回来
break;
}//对于大于等于左子树的情况,直接减去顶点并外接即可
//只有当伸展必须向子树的外侧纵深时才需要旋转调整高度
//将顶点剪去,暂时接在外部两侧的辅助树上
tr->lft = tree;
tr = tree;
tree = tree->lft;
}
else {//右伸展与左伸展同理
if ( !tree->rht )
break;
if ( p > tree->rht->p ) {
ttmp = tree->rht;
tree->rht = ttmp->lft;
ttmp->lft = tree;
tree = ttmp;
if ( !tree->rht )
break;
}
tl->rht = tree;
tl = tree;
tree = tree->rht;
}
}
//将暂接在外侧树上的子树接回来
tl->rht = tree->lft;
tr->lft = tree->rht;
tree->lft = node.rht;
tree->rht = node.lft;
return tree;
}
Tree
push( Tree tree, int k, int p ) {//插入结点
//插入的结点作为新的顶点
PtNode node;
node = (PtNode)malloc( sizeof(BNode) );
node->k = k;
node->p = p;
node->lft = NULL;
node->rht = NULL;
if ( !tree )
return node;
tree = splay( tree, p );//先按照插入点的权值
//将整棵树伸展一遍,这样可以有效
//降低树的高度,使之趋于平衡
//接着再进行插入
//此时顶点的权值和插入结点的权值非常相近
if ( p < tree->p ) {//若小于顶点
node->lft = tree->lft;
node->rht = tree;
tree->lft = NULL;
}
else {//大于顶点
node->rht = tree->rht;
node->lft = tree;
tree->rht = NULL;
}
return node;
}
Tree
pop( Tree tree, int p ) {//删除指定权值的结点
//本来该函数是只能删除指定权值的结点的,
//如果查询不到指定权值的结点将会在伸展后
//返回与其最接近的顶点
//但是这里由于题目的特殊性,只删除最大或最小
//权值,因此这里输入的参数p不是MAXP就是MINP
//因此在splay后,顶点必然就是最大或者最小的
//因此无论如何都可以删除
//并且由于题目中要求空树输出0,因此该功能就在函数外
//实现了,因此函数内就不再判断树空了
Tree ttmp;
ttmp = splay( tree, p );//伸展,将最大或者最小结点变成顶点
printf("%d\n", ttmp->k);//输出
if ( !ttmp->lft )//左子树为空则直接将右子树作为新树
tree = ttmp->rht;
else {
//否则用顶点的值对左子树进行伸展
//由于顶点一定比左子树中任何一个结点的值都大
//因此伸展后左子树的右子树必为空
//接着再以伸展后的左子树作为新树
//将老树的右子树接在其右子树上即可
tree = splay( ttmp->lft, ttmp->p );
tree->rht = ttmp->rht;
}
free(ttmp);
return tree;
}
int
main() {
int n;
int k, p;
Tree tree;
tree = NULL;
while ( scanf("%d", &n), n ) {
switch (n) {
case 1 :
scanf("%d%d", &k, &p);
tree = push( tree, k, p );
break;
case 2 :
if ( !tree ) {
puts("0");
break;
}
tree = pop( tree, MAXP );
break;
default :
if ( !tree ) {
puts("0");
break;
}
tree = pop( tree, MINP );
break;
}
}
return 0;
}
无注释代码:
#include <stdio.h>
#include <stdlib.h>
#define MAXP 10000000
#define MINP 0
struct Node;
typedef struct Node BNode;
typedef struct Node * PtNode;
typedef struct Node * Tree;
struct Node {
int k;
int p;
Tree lft;
Tree rht;
};
Tree
splay( Tree tree, int p ) {
if ( !tree )
return NULL;
BNode node;
Tree tl;
Tree tr;
Tree ttmp;
node.lft = NULL;
node.rht = NULL;
tl = &node;
tr = &node;
while (1) {
if ( p == tree->p )
break;
if ( p < tree->p ) {
if ( !tree->lft )
break;
if ( p < tree->lft->p ) {
ttmp = tree->lft;
tree->lft = ttmp->rht;
ttmp->rht = tree;
tree = ttmp;
if ( !tree->lft )
break;
}
tr->lft = tree;
tr = tree;
tree = tree->lft;
}
else {
if ( !tree->rht )
break;
if ( p > tree->rht->p ) {
ttmp = tree->rht;
tree->rht = ttmp->lft;
ttmp->lft = tree;
tree = ttmp;
if ( !tree->rht )
break;
}
tl->rht = tree;
tl = tree;
tree = tree->rht;
}
}
tl->rht = tree->lft;
tr->lft = tree->rht;
tree->lft = node.rht;
tree->rht = node.lft;
return tree;
}
Tree
push( Tree tree, int k, int p ) {
PtNode node;
node = (PtNode)malloc( sizeof(BNode) );
node->k = k;
node->p = p;
node->lft = NULL;
node->rht = NULL;
if ( !tree )
return node;
tree = splay( tree, p );
if ( p < tree->p ) {
node->lft = tree->lft;
node->rht = tree;
tree->lft = NULL;
}
else {
node->rht = tree->rht;
node->lft = tree;
tree->rht = NULL;
}
return node;
}
Tree
pop( Tree tree, int p ) {
Tree ttmp;
ttmp = splay( tree, p );
printf("%d\n", ttmp->k);
if ( !ttmp->lft )
tree = ttmp->rht;
else {
tree = splay( ttmp->lft, ttmp->p );
tree->rht = ttmp->rht;
}
free(ttmp);
return tree;
}
int
main() {
int n;
int k, p;
Tree tree;
tree = NULL;
while ( scanf("%d", &n), n ) {
switch (n) {
case 1 :
scanf("%d%d", &k, &p);
tree = push( tree, k, p );
break;
case 2 :
if ( !tree ) {
puts("0");
break;
}
tree = pop( tree, MAXP );
break;
default :
if ( !tree ) {
puts("0");
break;
}
tree = pop( tree, MINP );
break;
}
}
return 0;
}
STL:
注释代码:
/*
* Problem ID : POJ 3481 Double Queue
* Author : Lirx.t.Una
* Language : C++
* Run Time : 297 ms
* Run Memory : 196 KB
*/
#include <iostream>
#include <cstdio>
#include <map>
using namespace std;
int
main() {
map<int, int> mp;
map<int, int>::iterator it;//迭代器
int n;
int k, p;
//在map[i] = j中i为第一个参数,j为第二个参数
//i向j映射
//其中迭代顺序为按照i的大小从前往后排
//即map.begin()为i最小的元素的迭代器
//map.end() - 1为i最大的元素的迭代器
//迭代器重载过->运算符,其中
//it->first为第一个参数,即i
//it->second为第二个参数,即j
//map内部实现为红黑树
//此程序中map的几个调用
//mp.begin()、mp.end()返回起始和末尾元素的迭代器
//其中mp.end()指向的是最后一个元素的后面一个位置,其实是空的
//因此得到的it需要--
//mp.erase(it)将相应迭代器所指向的元素删去
//mp.empty()判断map是否为空
//it->first、it->second,返回迭代器所指元素的第一和第二参数
while ( scanf("%d", &n), n )
switch (n) {
case 1 :
scanf("%d%d", &k, &p);
mp[p] = k;
break;
case 2 :
if ( mp.empty() ) {
puts("0");
break;
}
it = mp.end();
printf("%d\n", (--it)->second);
mp.erase(it);
break;
default :
if ( mp.empty() ) {
puts("0");
break;
}
it = mp.begin();
printf("%d\n", it->second);
mp.erase(it);
break;
}
return 0;
}
无注释代码:
#include <iostream>
#include <cstdio>
#include <map>
using namespace std;
int
main() {
map<int, int> mp;
map<int, int>::iterator it;
int n;
int k, p;
while ( scanf("%d", &n), n )
switch (n) {
case 1 :
scanf("%d%d", &k, &p);
mp[p] = k;
break;
case 2 :
if ( mp.empty() ) {
puts("0");
break;
}
it = mp.end();
printf("%d\n", (--it)->second);
mp.erase(it);
break;
default :
if ( mp.empty() ) {
puts("0");
break;
}
it = mp.begin();
printf("%d\n", it->second);
mp.erase(it);
break;
}
return 0;
}
树堆(Treap):
注释代码:
/*
* Problem ID : POJ 3481 Double Queue
* Author : Lirx.t.Una
* Language : C/C++
* Run Time : 266 ms
* Run Memory : 196 KB
*/
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
struct Node;
typedef struct Node * PtNode;
typedef struct Node * Tree;
struct Node {
int k;
int p;
Tree lft;
Tree rht;
int fix;//随机修正值
};
Tree
RotL(Tree k2) {//AVL左旋
Tree k1;
k1 = k2->lft;
k2->lft = k1->rht;
k1->rht = k2;
return k1;
}
Tree
RotR(Tree k2) {//AVL右旋
Tree k1;
k1 = k2->rht;
k2->rht = k1->lft;
k1->lft = k2;
return k1;
}
Tree
Insert( Tree tree, int k, int p ) {//插入
if ( !tree ) {//正常的BST插入,并附上随机修正值
//插在叶结点上
PtNode node;
node = (PtNode)malloc( sizeof( struct Node ) );
node->k = k;
node->p = p;
node->lft = NULL;
node->rht = NULL;
node->fix = rand();
return node;
}
//调整高度时按照随机修正值小的往高处调的原则进行维护
//待调结点和顶点比较修正值大小
if ( p < tree->p ) {
tree->lft = Insert( tree->lft, k, p );
if ( tree->lft->fix < tree->fix )
tree = RotL(tree);
}
else {
tree->rht = Insert( tree->rht, k, p );
if ( tree->rht->fix < tree->fix )
tree = RotR(tree);
}
return tree;
}
Tree
Remove( Tree tree, int p ) {//删除相应权值的结点
if ( !tree )
return NULL;
if ( p == tree->p ) {//找到匹配结点
if ( !tree->lft || !tree->rht ) {//可以直接删除
Tree ttmp;
ttmp = tree;
if ( !tree->lft )
tree = tree->rht;
else
tree = tree->lft;
free(ttmp);
return tree;
}
//左右子树都非空,必须做调整后在进行删除
if ( tree->lft->fix < tree->rht->fix ) {
//按照随机修正值小的结点往上走的原则
//先将左子树顶点左旋至顶点位置,此时老顶点称为新顶点的右子树顶点了
//然后在右子树中删除匹配结点就行了
tree = RotL(tree);
tree->rht = Remove( tree->rht, p );
}
else {//与上对称,同理
tree = RotR(tree);
tree->lft = Remove( tree->lft, p );
}
return tree;
}
if ( p < tree->p )
tree->lft = Remove( tree->lft, p );
else
tree->rht = Remove( tree->rht, p );
return tree;
}
int
MinP(Tree tree) {//get minimum priority in tree
//获得tree中权值最小的顶点的权值
while ( tree->lft )
tree = tree->lft;
printf("%d\n", tree->k);//顺便输出最小结点的编号值
return tree->p;
}
int
MaxP(Tree tree) {//get maximum priority in tree
while ( tree->rht )
tree = tree->rht;
printf("%d\n", tree->k);
return tree->p;
}
int
main() {
int n;
int k, p;
Tree tree;
tree = NULL;
srand( (unsigned int)time(NULL) );
while ( scanf("%d", &n), n )
switch (n) {
case 1 :
scanf("%d%d", &k, &p);
tree = Insert( tree, k, p );
break;
case 2 :
if ( !tree ) {
puts("0");
break;
}
tree = Remove( tree, MaxP(tree) );
break;
default :
if ( !tree ) {
puts("0");
break;
}
tree = Remove( tree, MinP(tree) );
break;
}
return 0;
}
无注释代码:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
struct Node;
typedef struct Node * PtNode;
typedef struct Node * Tree;
struct Node {
int k;
int p;
Tree lft;
Tree rht;
int fix;
};
Tree
RotL(Tree k2) {
Tree k1;
k1 = k2->lft;
k2->lft = k1->rht;
k1->rht = k2;
return k1;
}
Tree
RotR(Tree k2) {
Tree k1;
k1 = k2->rht;
k2->rht = k1->lft;
k1->lft = k2;
return k1;
}
Tree
Insert( Tree tree, int k, int p ) {
if ( !tree ) {
PtNode node;
node = (PtNode)malloc( sizeof( struct Node ) );
node->k = k;
node->p = p;
node->lft = NULL;
node->rht = NULL;
node->fix = rand();
return node;
}
if ( p < tree->p ) {
tree->lft = Insert( tree->lft, k, p );
if ( tree->lft->fix < tree->fix )
tree = RotL(tree);
}
else {
tree->rht = Insert( tree->rht, k, p );
if ( tree->rht->fix < tree->fix )
tree = RotR(tree);
}
return tree;
}
Tree
Remove( Tree tree, int p ) {
if ( !tree )
return NULL;
if ( p == tree->p ) {
if ( !tree->lft || !tree->rht ) {
Tree ttmp;
ttmp = tree;
if ( !tree->lft )
tree = tree->rht;
else
tree = tree->lft;
free(ttmp);
return tree;
}
if ( tree->lft->fix < tree->rht->fix ) {
tree = RotL(tree);
tree->rht = Remove( tree->rht, p );
}
else {
tree = RotR(tree);
tree->lft = Remove( tree->lft, p );
}
return tree;
}
if ( p < tree->p )
tree->lft = Remove( tree->lft, p );
else
tree->rht = Remove( tree->rht, p );
return tree;
}
int
MinP(Tree tree) {
while ( tree->lft )
tree = tree->lft;
printf("%d\n", tree->k);
return tree->p;
}
int
MaxP(Tree tree) {
while ( tree->rht )
tree = tree->rht;
printf("%d\n", tree->k);
return tree->p;
}
int
main() {
int n;
int k, p;
Tree tree;
tree = NULL;
srand( (unsigned int)time(NULL) );
while ( scanf("%d", &n), n )
switch (n) {
case 1 :
scanf("%d%d", &k, &p);
tree = Insert( tree, k, p );
break;
case 2 :
if ( !tree ) {
puts("0");
break;
}
tree = Remove( tree, MaxP(tree) );
break;
default :
if ( !tree ) {
puts("0");
break;
}
tree = Remove( tree, MinP(tree) );
break;
}
return 0;
}
单词解释:
found:vt, 创立,创办
Balkan:地名,巴尔干半岛(即意大利陆地)
investment:n, 投资
Bucharest:地名,布加勒斯特(罗马尼亚首都)
equip:vt, 装备
Romania:国家,罗马尼亚
client:n, 客户,客户机
upon:prep, 根据
identify:vt, 鉴定,识别
invention:n, 发明
shock:vt, 震惊
propose:vt, 建议,打算
request:n, 请求,要求
serving desk:n, 服务柜台
identifier:n, 标示符