关于Size Balanced Tree的讲解可以查看发明者陈启峰的PPT:
http://wenku.baidu.com/view/ef481548cf84b9d528ea7a56.html
或者论文:
http://wenku.baidu.com/view/364afa42a8956bec0975e3b1.html
我就不搬运了~
set和map内部是使用红黑树实现的,故其中的数据是有序的,也可以用来解此题,而且两者的时间空间使用都一模一样。
进一步了解红黑树:http://blog.csdn.net/iceteaset/article/details/48032497
我全部使用inline的红黑树可以达到250ms,比下面的SBT更快一点点。或许是实现方式的问题。不过就算SBT真的慢一点点,它的代码长度可不止短了一点点。
以下代码均可以在poj3481上测试其正确性和时间。
SBT:
#include<iostream>
//192K 282MS
struct Key //单独设置一个struct是为了方便修改(value域不可删除)
{
int value,num;
};
struct SBNode //省略了parent域,不过也导致insert,delete只能使用递归
{
Key key;
int size;
SBNode* c[2];
SBNode(){}
SBNode(const Key& k){
key=k;
size=1;
}
};
class SBTree
{
private:
SBNode* root,*nil;
inline void rotate(SBNode*& x,bool l) //根据l的值(LEFT/RIGHT)进行左右旋
{
SBNode* y=x->c[!l];
x->c[!l]=y->c[l];
y->c[l]=x;
y->size=x->size;
x->size=x->c[l]->size+x->c[!l]->size+1;
x=y;
}
inline bool cmp(const Key& k1,const Key& k2) //自定义比较函数
{
if (k1.value<k2.value) return LEFT;
else return RIGHT;
}
inline void maintain(SBNode * &x , bool l) //根据l的值(LEFT/RIGHT)进行左右子树的维护
{
if (x->c[l]->c[l]->size>x->c[!l]->size)
rotate(x,!l);
else if (x->c[l]->c[!l]->size>x->c[!l]->size){
rotate(x->c[l],l);
rotate(x,!l);
}else return;
maintain(x->c[l],l);
maintain(x->c[!l],!l);
maintain(x,l);
maintain(x,!l);
}
public:
SBTree(){nil=new SBNode;nil->size=0;nil->c[0]=nil;nil->c[1]=nil;root=nil;}
~SBTree(){delete nil;}
const static bool LEFT=false,RIGHT=true; //增强可读性
inline void insert(const Key& key){insert(root,key);} //重载是为了方便调用
inline void insert(SBNode*& x,const Key& key)
{
if (x==nil)
{
x=new SBNode(key);
x->c[0]=nil;
x->c[1]=nil;
}else{
x->size++;
bool lr=cmp(key,x->key);
insert(x->c[lr],key); //递归进下一层
maintain(x,lr);
}
}
inline bool del(const Key& key){return del(root,key);}
inline bool del(SBNode*& x,const Key& key)
{
if (x==nil)
return false;
if (cmp(key,x->key) && cmp(x->key,key)) //如果Key相等,即找到了
{
if (x->c[LEFT]!=nil && x->c[RIGHT]!=nil) //如果有两个孩子,
{
SBNode* temp=x->c[RIGHT];
while (temp->c[LEFT]!=nil)
temp=temp->c[LEFT];
x->key=temp->key; //则用后继的Key代替当前的Key,
x->size--;
del(x->c[RIGHT],temp->key); //然后继续递归,目标改为了后继
return true;
}
bool lr=x->c[LEFT]!=nil? LEFT:RIGHT;
SBNode* temp=x;
x=x->c[lr];
delete temp;
return true;
}else{
bool lr= cmp(key,x->key);
if (del(x->c[lr],key)) //递归进下一层
x->size--;
}
}
inline SBNode* findMost(bool lr) //找树中最大值/最小值
{
SBNode *p=root;
if (p==nil) return NULL;
else{
while (p->c[lr] != nil) p = p->c[lr];
return p;
}
}
};
int main()
{
SBTree* tree=new SBTree;
int no,k,p;
while (scanf("%d",&no),no)
{
SBNode* nod;
Key key;
switch (no)
{
case 1:
scanf("%d%d",&k,&p);
key.value=p;
key.num=k;
tree->insert(key);
break;
case 2:
nod=tree->findMost(SBTree::RIGHT);
printf("%d\n",nod==NULL?0:nod->key.num);
if (nod!=NULL) tree->del(nod->key);
break;
case 3:
nod=tree->findMost(SBTree::LEFT);
printf("%d\n",nod==NULL?0:nod->key.num);
if (nod!=NULL) tree->del(nod->key);
break;
}
}
return 0;
}
set:
#include<iostream>
#include<set>
//196K 282MS
using namespace std;
struct Key
{
int value,num;
};
class Cmp{
public:
inline bool operator()(const Key& a,const Key& b)
{
return a.value>b.value;
}
};
int main()
{
set<Key,Cmp> s;
int no,k,p;
Key key;
set<Key,Cmp>::iterator i;
while (scanf("%d",&no),no)
{
switch (no)
{
case 1:
scanf("%d%d",&k,&p);
key.value=p;
key.num=k;
s.insert(key);
break;
case 2:
if (s.empty())
printf("%d\n",0);
else
{
i=s.begin();
printf("%d\n",(*i).num);
s.erase(i);
}
break;
case 3:
if (s.empty())
printf("%d\n",0);
else
{
i=s.end();
i--;
printf("%d\n",(*i).num);
s.erase(i);
}
break;
}
}
return 0;
}
map:
#include<iostream>
#include<map>
//196K 282MS
using namespace std;
int main()
{
int no,k,p;
map<int,int> m;
map<int,int>::iterator i;
while (scanf("%d",&no),no)
{
switch (no)
{
case 1:
scanf("%d%d",&k,&p);
m[p]=k;
break;
case 2:
if (m.empty())
printf("%d\n",0);
else
{
i=m.end();
i--;
printf("%d\n",(*i).second);
m.erase(i);
}
break;
case 3:
if (m.empty())
printf("%d\n",0);
else
{
i=m.begin();
printf("%d\n",(*i).second);
m.erase(i);
}
break;
}
}
return 0;
}