题目传送门
解题思路
三种操作,插入一个数,取最大值并删除,取最小值并删除。
应该有挺多方法可以做的。
提供无旋treap和Splay这两种平衡树的数组的做法。
代码
无旋treap版本
#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
#define for1(i,a,b) for (int i=a;i<=b;i++)
#define for0(i,a,b) for (int i=a;i<b;i++)
#define pt(x) printf("%s = %I64d\n",#x,(ll)x)
#define maxint ((1LL<<31)-1)
#define lson ch[rt][0]
#define rson ch[rt][1]
const int N = 1e6+5;
struct fhq_treap
{
int ch[N][2];
int pri[N];
int id[N],pr[N];
int size[N];
int root,sz;
void init(){
root = 0;
sz = 1;
}
int rand(){
static int seed = 1433223;
return seed = (int)(1LL*seed*233%maxint);
}
int newnode(int idx,int prior){
ch[sz][0] = ch[sz][1] = 0;
pri[sz] = rand();
id[sz] = idx,pr[sz] = prior;
size[sz] = 1;
return sz++;
}
void push_up(int rt){size[rt] = 1 + lson + rson;}
int merge(int x,int y){
if (!x || !y) return x+y;
else {
//push_down(x),push_down(y);
if (pri[x] > pri[y]){
ch[x][1] = merge(ch[x][1],y);
push_up(x);
return x;
}
else {
ch[y][0] = merge(x,ch[y][0]);
push_up(y);
return y;
}
}
}
void split(int rt,int v,int&x,int&y){
if (!rt) x = y = 0;
else {
if (pr[rt]<=v){
x = rt;
split(ch[rt][1],v,ch[rt][1],y);
}
else {
y = rt;
split(ch[rt][0],v,x,ch[rt][0]);
}
push_up(rt);
}
}
void insert(int idx,int prior){
int x,y;
split(root,prior-1,x,y);
root = merge(merge(x,newnode(idx,prior)),y);
}
void remove(int p){
int x,y,z;
split(root,pr[p]-1,x,y);
split(y,pr[p],y,z);
root = merge(x,z);
}
int getmax(){
if (!root) return 0;
int now = root;
while (ch[now][1]) now = ch[now][1];
int ans = id[now];
remove(now);
return ans;
}
int getmin(){
if (!root) return 0;
int now = root;
while (ch[now][0]) now = ch[now][0];
int ans = id[now];
remove(now);
return ans;
}
/*
void DE(){dfs1(root);puts("");}//get the order
void dfs1(int rt){
if (!rt) return ;
if (lson) dfs1(lson);
printf("[%d,%d] ",id[rt],pr[rt]);
//printf("fa[%d]=%d,pr[%d]=%d,id[%d]=%d,size[%d]=%d\n",rt,fa[rt],rt,pr[rt],rt,id[rt],rt,size[rt]);
if (rson) dfs1(rson);
}
void BUG(){dfs2(root);}//get the tree
void dfs2(int rt){
if (!rt) return ;
printf("%d:%d %d\n",rt,lson,rson);
dfs2(lson);dfs2(rson);
}
*/
}tp;
int main()
{
tp.init();
int op,idx,prior;
while (scanf("%d",&op),op){
if (op==1) scanf("%d %d",&idx,&prior),tp.insert(idx,prior);
if (op==2) printf("%d\n",tp.getmax());
if (op==3) printf("%d\n",tp.getmin());
//tp.DE();
//tp.BUG();
}
return 0;
}
Splay版本
#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
#define for1(i,a,b) for (int i=a;i<=b;i++)
#define for0(i,a,b) for (int i=a;i<b;i++)
#define pt(x) printf("%s = %I64d\n",#x,(ll)x)
#define lson ch[rt][0]
#define rson ch[rt][1]
const int N = 1e6+5;
struct SPLAY
{
int ch[N][2];
int id[N],pr[N];
int fa[N];
int size[N];
int sz,root;
void init(){
root = 0;
sz = 1;
}
int newnode(int idx,int prior,int f){
ch[sz][0] = ch[sz][1] = 0;
id[sz] = idx,pr[sz] = prior;
fa[sz] = f;
size[sz] = 1;
return sz++;
}
void push_up(int rt){
size[rt] = 1 + size[lson] + size[rson];
}
void rotate(int x){
int f = fa[x];
int d = ch[f][0] == x? 1:0;
fa[x] = fa[f],fa[f] = x,fa[ch[x][d]] = f;
ch[f][d^1] = ch[x][d],ch[x][d] = f;
if (fa[x]) ch[fa[x]][ch[fa[x]][0]==f?0:1] = x;
push_up(f),push_up(x);
}
void splay(int x,int goal=0){
while (fa[x]!=goal){
int f = fa[x],g = fa[f];
if (g!=goal) rotate((ch[f][0]==x)==(ch[g][0]==f)?f:x);
rotate(x);
}
if (!goal) root = x;
}
int rank(int x){//查询pr=x的数的排名
int ans = 0,now = root;
while (now){
//push_down(now);
if (x < pr[now]) {now = ch[now][0];continue;}
ans += size[ch[now][0]] + 1;
if (x==pr[now]) {return ans;}
else now = ch[now][1];
}
}
int kth(int rt,int k){//查询排名为k的数的下标
//push_down()
if (k<=size[lson]) return kth(lson,k);//翻车翻在奇怪的地方,写成了return lson,f***
k -= size[lson] + 1;
if (k<=0) return rt;
else return kth(rson,k);
}
void insert(int idx,int prior){
int now = root,f = 0;
while (now /* && pr[now]!=prior */) f = now,now = ch[now][prior>pr[now]];
now = newnode(idx,prior,f);
ch[f][prior>pr[f]] = now;
splay(now);//用于push_up一遍所有祖先节点
}
void remove(int x){//传入的是一个节点下标
int p = rank(pr[x]),ls,rs,ccnt = size[root];
if (ccnt==1) root = 0;
else if (p==ccnt) ls = kth(root,p-1),splay(ls),ch[root][1] = 0,push_up(root);
else if (p==1) rs = kth(root,p+1),splay(rs),ch[root][0] = 0,push_up(root);
else {
ls = kth(root,p-1),rs = kth(root,p+1);
splay(ls),splay(rs,root);
ch[ch[root][1]][0] = 0;
push_up(ch[root][1]),push_up(root);
}
}
int getmax(){
if (!root) return 0;
int now = root;
while (ch[now][1]) now = ch[now][1];
int ans = id[now];
remove(now);
return ans;
}
int getmin(){
if (!root) return 0;
int now = root;
while (ch[now][0]) now = ch[now][0];
int ans = id[now];
remove(now);
return ans;
}
/*
void DE(){dfs1(root);puts("");}//get the order
void dfs1(int rt){
if (!rt) return ;
if (lson) dfs1(lson);
printf("[%d,%d] ",id[rt],pr[rt]);
//printf("fa[%d]=%d,pr[%d]=%d,id[%d]=%d,size[%d]=%d\n",rt,fa[rt],rt,pr[rt],rt,id[rt],rt,size[rt]);
if (rson) dfs1(rson);
}
void BUG(){dfs2(root);}//get the tree
void dfs2(int rt){
if (!rt) return ;
printf("%d:%d %d\n",rt,lson,rson);
dfs2(lson);dfs2(rson);
}
*/
}sp;
int main()
{
sp.init();
int op,idx,prior;
while (scanf("%d",&op),op){
if (op==1) scanf("%d %d",&idx,&prior),sp.insert(idx,prior);
if (op==2) printf("%d\n",sp.getmax());
if (op==3) printf("%d\n",sp.getmin());
//sp.DE();
//sp.BUG();
}
return 0;
}