poj 3481 double Queue(Splay树 模板解读)
来源:互联网 发布:如何编写python程序 编辑:程序博客网 时间:2024/05/01 09:25
题意:
每个顾客有个编号和优先级,银行每次可以添加顾客的要求进队列,
且保证队列中当前任意顾客的编号和优先级都不同.
银行可以执行先服务最大优先级的顾客或者先服务最小优先级的顾客操作.
对于每个服务,输出顾客的编号.
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <cstdlib>#include <cmath>#include <utility>#include <vector>#include <queue>#include <map>#include <set>#define max(x,y) ((x)>(y)?(x):(y))#define min(x,y) ((x)>(y)?(y):(x))#define INF 0x3f3f3f3f#define MAXN 100005using namespace std;int cnt=1,rt=0;struct Tree{ int key,size,fa,son[2],num; void set(int _key,int _size,int _fa,int _num) { key=_key; size=_size; fa=_fa; son[0]=son[1]=0; num=_num; }}T[MAXN];inline void PushUp(int x){ T[x].size=T[T[x].son[0]].size+T[T[x].son[1]].size+1;}inline void Rotate(int x,int p){ int y=T[x].fa; T[y].son[!p]=T[x].son[p]; T[T[x].son[p]].fa=y; T[x].fa=T[y].fa; if(T[x].fa) T[T[x].fa].son[T[T[x].fa].son[1]==y]=x; T[x].son[p]=y; T[y].fa=x; PushUp(y); PushUp(x);}void Splay(int x,int To){ while(T[x].fa!=To) //直到父节点为To { if(T[T[x].fa].fa==To) //如果父节点的父节点==To 单旋 Rotate(x,T[T[x].fa].son[0]==x); else //如果的父节点的父节点!=to 双旋 { int y=T[x].fa,z=T[y].fa; //y是父节点,z是父节点的父节点 int p=(T[z].son[0]==y);//y是不是在父节点的0路线 if(T[y].son[p]==x) //这里判断是不是和父节点所在路线相反 Rotate(x,!p),Rotate(x,p);// 如果相反 就是之字形 else Rotate(y,p),Rotate(x,p);//相同 一字型 } } if(To==0) rt=x;}int prev(){ int x=T[rt].son[0]; if(!x) return 0; while(T[x].son[1]) x=T[x].son[1]; return x;}int succ(){ int x=T[rt].son[1]; if(!x)return 0; while(T[x].son[0]) x=T[x].son[0]; Splay(x,0); return x;}void Insert(int key,int num)//插入key 并且将该节点转移到根处{ if(!rt) T[rt=cnt++].set(key,1,0,num); else { int x=rt,y=0; while(x) { y=x; x=T[x].son[key>T[x].key]; } T[x = cnt++].set(key,1,y,num); T[y].son[key>T[y].key]=x; Splay(x,0); }}int find(int key) //返回值为key的节点 若无返回0 若有将其转移到根处{ int x=rt; while(x&&T[x].key!=key) x=T[x].son[key>T[x].key]; if(x) Splay(x,0); return x;}int GetPth(int p) //获得第p小的节点 并将其转移到根处{ if(!rt) return 0; int x=rt,ret=0; while(x) { if(p==T[T[x].son[0]].size+1) break; if(p>T[T[x].son[0]].size+1) //判断是第p个是在左边还是右边 { p-=T[T[x].son[0]].size+1; x=T[x].son[1]; } else x=T[x].son[0]; } Splay(x,0); return x;}void Delete(int key)//删除值为key的节点 若有重点只删其中一个 x的前驱移动到根处{ int x=find(key); //找到与key值相同的 if(!x) return ; //如果没有就return int y=T[x].son[0]; while(T[y].son[1]) //找到左边叶子结点 y=T[y].son[1]; int z=T[x].son[1]; //找到右边叶子结点 while(T[z].son[0]) z=T[z].son[0]; if(!y&&!z) //如果这是根结点 { rt=0; return ; } if(!y) //只有右叶子结点 { Splay(z,0); //把z调到最高点然后把x删去 T[z].son[0]=0; //把x删去 PushUp(z); return ; } if(!z) //只有左叶子结点 { Splay(y,0); T[y].son[1]=0; //把y调到最低点然后把x删去 PushUp(y); //把x删去 return ; } Splay(y,0); Splay(z,y); T[z].son[0]=0; PushUp(z); PushUp(y);}int main (){ int p, key, num, x; while(scanf("%d", &p) && p) { switch (p) { case 1: scanf("%d%d", &num, &key); Insert(key, num); break; case 2: x=GetPth(T[rt].size); if(x) { printf("%d\n",T[x].num); Delete(T[x].key); } else printf("0\n"); break; case 3: x=GetPth(1); if(x) { printf("%d\n",T[x].num); Delete(T[x].key); } else printf("0\n"); } } return 0;}
另一个模板
#include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> #include<vector> using namespace std; #define maxn 1100000 #define mem(a,b) memset(a,b,sizeof(a)) #define root10 ch[ch[root][1]][0] #define root1 ch[root][1] int size[maxn]; int ch[maxn][2]; int pre[maxn]; int root,tot; int key[maxn]; int val[maxn]; int n; int pos; void Treaval(int x) { if(x) { Treaval(ch[x][0]); printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,key = %2d \n",x,ch[x][0],ch[x][1],pre[x],size[x],key[x]); Treaval(ch[x][1]); } } void debug() {printf("root:%d\n",root);Treaval(root);} //以上Debug void init() { } void newnode(int &x,int k,int p,int father) { x=++tot; pre[x]=father; size[x]=1; ch[x][0]=ch[x][1]=0; key[x]=p; val[x]=k; } void push_down(int x) { } void push_up(int x) { } void rot(int x,int kind) { int y=pre[x]; push_down(y); push_down(x); ch[y][!kind]=ch[x][kind]; pre[ch[x][kind]]=y; if(pre[y])ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y]; ch[x][kind]=y; pre[y]=x; push_up(y); push_up(x); } void splay(int x,int goal) { push_down(x); while(pre[x]!=goal) { if(pre[pre[x]]==goal) { push_down(pre[x]); push_down(x); rot(x,ch[pre[x]][0]==x); } else { int y=pre[x]; push_down(pre[y]); push_down(y); push_down(x); int kind=ch[pre[y]][0]==y; if(ch[y][kind]==x) { rot(x,!kind); rot(x,kind); } else { rot(y,kind); rot(x,kind); } } } push_up(x); if(goal==0)root=x; } void insert(int k,int p) { int rt=root; int r=root; while(rt!=0) { r=rt; if(key[rt]<p)rt=ch[rt][1]; else rt=ch[rt][0]; //cout<<r<<" "<<rt<<endl; } newnode(ch[r][key[r]<p],k,p,r); splay(ch[r][key[r]<p],root); ch[0][0]=ch[0][1]=0; } int get_min(int rt) { while(ch[rt][0])rt=ch[rt][0]; if(rt==root)root=ch[rt][1]; ch[pre[rt]][0]=ch[rt][1]; pre[ch[rt][1]]=pre[rt]; return val[rt]; } int get_max(int rt) { while(ch[rt][1])rt=ch[rt][1]; if(rt==root)root=ch[rt][0]; ch[pre[rt]][1]=ch[rt][0]; pre[ch[rt][0]]=pre[rt]; return val[rt]; } int main() { root=tot=0; int op,k,p; while(~scanf("%d",&op)&&(op)) { if(op==1) { scanf("%d%d",&k,&p); insert(k,p); } if(op==2) { printf("%d\n",get_max(root)); } if(op==3) { printf("%d\n",get_min(root)); } // debug(); } return 0; }
0 0
- poj 3481 double Queue(Splay树 模板解读)
- POJ-3481 Double Queue (平衡树 入门题 splay模板题)
- POJ 3481 Double Queue(Splay)
- POJ 3481 Double Queue (Splay || 水题)
- poj 3481 Double Queue splay
- POJ 3481 Double Queue [splay]
- poj-3481-Double Queue-splay树的水题
- POJ 3481 Double Queue 伸展树splay + 删除节点
- AVL树(模板题)—— POJ 3481 Double Queue
- poj 3481 Double Queue
- Double Queue POJ 3481
- POJ 3481 Double Queue
- POJ 3481 Double Queue
- POJ 3481 Double Queue
- POJ 3481 Double Queue
- POJ 3481 Double Queue
- poj 3481 Double Queue
- poj 3481 Double Queue
- HTML常用标签
- windows关闭进程 批处理端口占用
- ACM另一种阶乘问题
- 骑士游历
- 博客搬家
- poj 3481 double Queue(Splay树 模板解读)
- 数值转换成大写金额运算
- 第一道非二叉树题
- 关于TCP、HTTP、Socket的自我理解
- 第七届蓝桥杯大学生C组java决赛题目 密文搜索
- git 推送多个远程仓库
- 续写
- 【04】SSH练习——简单分页查询的实现
- 解析argc argv在php中的应用