题面在这里
(vjudge怎么这么不靠谱啊。。以后还是直接用poj算了)
(注册了一个号写了一道题Submissions:14===)
呐,进入正题。
题意:
三个操作:
1. 插入一个编号为x,优先级为y的人
2. 返回优先级最高的人的编号
3. 返回优先级最低的人的编号
做法:
treap模板。(这题我好像也写过splay)
大致的想法就是,tree+heap,对于每一个节点维护一个数值,一个优先级,对于数值保持二叉搜索树,对于优先级保持一个堆(大根堆小根堆都可以)。优先级是人为规定的,一般用随机数,这样靠随机性保证复杂度是log的。
然后你会发现treap比splay好写多了QAQ。尤其是旋转。
代码里有注释。
然后说一下为什么提交这么多次。。因为原来写了一个srand(time(NULL)),然后poj就疯狂爆re= =
代码:
/*************************************************************
Problem: poj 3481 Double Queue
User: fengyuan
Language: C++
Result: Accepted
Time: 422MS
Memory: 2276K
Submit_Time: 2018-01-01 15:49:33
*************************************************************/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<cstdlib>
using namespace std;
const int N = 100010;
int tot = 0, rt = 0;
struct Treap{
int id, key, p, ch[2];//p是优先级,保持优先级为一个大根堆
void set(int x, int y, int z) {
key = x; id = y; p = z;
ch[0] = ch[1] = 0;
}
}T[N];
inline void rot(int &x, int p)//哇treap的旋转比splay好写一万倍啊!!
{
//p=1表示向左旋,右儿子变成根
//p=0表示向右旋,左儿子变成根
int y = T[x].ch[p];
T[x].ch[p] = T[y].ch[p^1];
T[y].ch[p^1] = x; x = y;
}
inline void insert(int &rt, int key, int id)
{
if(!rt) T[rt = ++ tot].set(key, id, rand());//依靠随机化实现深度为log
else {
int p = key >= T[rt].key;//p=1代表向右插入,p=0代表向左插入
insert(T[rt].ch[p], key, id);
if(T[rt].p < T[T[rt].ch[p]].p) rot(rt, p);//如果优先级不对就旋转,保持平衡
}
}
inline void del(int &rt, int key)
{
if(T[rt].key == key) {
if(T[rt].ch[0] && T[rt].ch[1]) {
int p = T[T[rt].ch[0]].p < T[T[rt].ch[1]].p;
rot(rt, p); del(T[rt].ch[p^1], key);//把rt这个节点一直旋到底
} else {
int t = rt;
if(T[rt].ch[0]) rt = T[rt].ch[0]; else rt = T[rt].ch[1]; T[t].set(0, 0, 0);
}
} else del(T[rt].ch[key >= T[rt].key], key);
}
inline int get(int rt, int p)//p=1表示查找最大值,p=0表示查找最小值
{
while(T[rt].ch[p]) rt = T[rt].ch[p];
return rt;//返回节点标号
}
int main()
{
int opt, x, y, all = 0;
while(~scanf("%d", &opt) && opt) {
if(opt == 1) {
scanf("%d%d", &x, &y);
insert(rt, y, x);
all ++;
} else if(opt == 2) {
if(!all) { puts("0"); continue; }
x = get(rt, 1);
printf("%d\n", T[x].id);
del(rt, T[x].key);
all --;
} else {
if(!all) { puts("0"); continue; }
x = get(rt, 0);
printf("%d\n", T[x].id);
del(rt, T[x].key);
all --;
}
}
return 0;
}