一道 treap 水题
题干如下,有 n 个客户,每个客户有一个优先度,我们需要3个操作
1 X Y 加入ID为 X ,优先度为 Y 的客户
2 提取出优先度最大的客户
3 提取出优先度最小的客户
乍一看 感觉堆可以解决, 但是我们发现 不但需要最大,还需要最小,那么我们便用 treap 解决即可。。
之前尝试用了 hzwer 模板。。A是A掉了。。但是感觉有点显得太长了,另外也想用一下指针,所以自己加上参考搞了个指针版本的。。。Treap 详细解读在下一篇
解题思路很简单了。。不断地找最左和最右,一旦根是空的就输出 0 。
以下是 AC 代码
#include<cctype>
#include<cstdio>
#include<cstdlib>//poj 万能头文件用不了
using namespace std;
const int maxn = 1e5+5;
inline int read()
{
int X=0,w=0; char ch=0;
while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
return w?-X:X;
}
struct Node
{
Node *ch[2];
int r,v,id;
Node(int v,int id):v(v),id(id)
{
r=rand();
ch[0]=ch[1]=NULL;
}
int cmp(int x)
{
if(x==v) return -1;
return x<v? 0:1;
}
};
void rotate(Node* &o,int d)
{
Node *k = o->ch[d^1];
o->ch[d^1] = k->ch[d]; k->ch[d] = o;
o=k;
}
void insert(Node* &o,int v,int id)
{
if(o==NULL) o=new Node(v,id);
else
{
int d = (v < o->v) ? 0:1;
insert(o->ch[d],v,id);
if(o->ch[d]->r > o->r)
rotate(o,d^1);
}
}
void del(Node *&o,int v)
{
int d = o->cmp(v);
if(d==-1)
{
Node *u=o;
if(o->ch[0] && o->ch[1])
{
int d2 = (o->ch[0]->r < o->ch[1]->r) ? 0:1;
rotate(o,d2);
del(o->ch[d2],v);
}
else
{
if(o->ch[0]==NULL) o=o->ch[1];
else o=o->ch[0];
delete u;
}
}
else del(o->ch[d],v);
}
int find_max(Node *o)
{
if(o->ch[1]==NULL)
{
printf("%d\n",o->id);
return o->v;
}
return find_max(o->ch[1]);
}
int find_min(Node *o)
{
if(o->ch[0]==NULL)
{
printf("%d\n",o->id);
return o->v;
}
return find_min(o->ch[0]);
}
int main()
{
int t;
Node *root = NULL;
while(true)
{
t=read();
if(t == 0)break;
else if(t == 1)
{
int id=read(), v=read();
insert(root, v, id);
}
else if(t == 2)
{
if(root == NULL) {printf("0\n"); continue;}
int temp = find_max(root);
del(root, temp);
}
else
{
if(root == NULL) {printf("0\n"); continue;}
int temp = find_min(root);
del(root, temp);
}
}
return 0;
}