http://blog.csdn.net/acceptedxukai/article/details/6921334
例题:poj3481
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string.h>
#include <queue>
#define N 100010
using namespace std; //poj3481
//SBT模板题
struct SBT
{
int key,left,right,size,num; //num是特别添加的(题意)
} tree[N];
int root,top;
void left_rot(int &x)
{
int y = tree[x].right;
tree[x].right = tree[y].left;
tree[y].left = x;
tree[y].size = tree[x].size;//转上去的节点数量为先前此处节点的size
tree[x].size = tree[tree[x].left].size + tree[tree[x].right].size + 1;
x = y;
}
void right_rot(int &x)
{
int y = tree[x].left;
tree[x].left = tree[y].right;
tree[y].right = x;
tree[y].size = tree[x].size;
tree[x].size = tree[tree[x].left].size + tree[tree[x].right].size + 1;
x = y;
}
void maintain(int &x,bool flag)
{
if(flag == false)//左边
{
if(tree[tree[tree[x].left].left].size > tree[tree[x].right].size)//左孩子的左子树大于右孩子
right_rot(x);
else if(tree[tree[tree[x].left].right].size > tree[tree[x].right].size)//右孩子的右子树大于右孩子
{
left_rot(tree[x].left);
right_rot(x);
}
else return;
}
else //右边
{
if(tree[tree[tree[x].right].right].size > tree[tree[x].left].size)//右孩子的右子树大于左孩子
left_rot(x);
else if(tree[tree[tree[x].right].left].size > tree[tree[x].left].size)//右孩子的左子树大于左孩子
{
right_rot(tree[x].right);
left_rot(x);
}
else return;
}
maintain(tree[x].left,false);
maintain(tree[x].right,true);
maintain(x,true);
maintain(x,false);
}
/*
*insert没有合并相同的元素,如果出现相同的元素则把它放到右子树上,这样能保证求第k小数的时候对相同元素也能正确
*/
void insert(int &x,int key, int num)
{
if(x == 0)
{
x = ++top;
tree[x].left = tree[x].right = 0;
tree[x].size = 1;
tree[x].key = key;
tree[x].num=num;
}
else
{
tree[x].size ++;
if(key < tree[x].key) insert(tree[x].left,key,num);
else insert(tree[x].right,key, num);//相同元素插入到右子树中
maintain(x, key >= tree[x].key);//每次插入把平衡操作压入栈中
}
}
int remove(int &x,int key)
{
int d_key;
//if(!x) return 0;
tree[x].size --;
if((key == tree[x].key)||(key < tree[x].key && tree[x].left == 0) ||
(key>tree[x].key && tree[x].right == 0))
{
d_key = tree[x].key;
if(tree[x].left && tree[x].right)
{
tree[x].key = remove(tree[x].left,tree[x].key+1);
}
else
{
x = tree[x].left + tree[x].right;
}
}
else if(key > tree[x].key)
d_key = remove(tree[x].right,key);
else if(key < tree[x].key)
d_key = remove(tree[x].left,key);
return d_key;
}
int getmin()
{
int x, k;
for(x = root ; tree[x].left; x = tree[x].left);
k=tree[x].num;
remove(root, tree[x].key); //输出最小值后要删除这个节点
return k;
}
int getmax()
{
int x, k;
for(x = root ; tree[x].right; x = tree[x].right);
k=tree[x].num;
remove(root, tree[x].key); //输出最大值后要删除这个节点
return k;
}
int main()
{
int n, a, b;
root=top=0;
while(scanf("%d", &n)&&n)
{
if(n==1)
{
scanf("%d%d" ,&a, &b);
insert(root, b, a);
}
if(n==2)
{
printf("%d\n", getmax());
}
if(n==3)
{
printf("%d\n", getmin());
}
}
return 0;
}