three kind of operation:
op1: insert client whose id is x and priority is p to queue
op2: get the client with **highest** priority and drop him from the queue
op2: get the client with **lowest** priority abd drio him from the queue
此处由于每种权值的顾客只会有一个,则所有点的num都一定为1,没有用了,可以用num表示某权值对应的顾客id;
要注意的是sum的修改此时不根据各点的num来了,而是仅+1(newnode(),update(),insert()中对sum有修改)
#include <cstdio>
#define lchild(x) (T[x].ch[0])
#define rchild(x) (T[x].ch[1])
#define fa(x) (T[x].fa)
#define root (T[0].ch[1])
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
int n,cnt;
ll ans=1e18;
struct node{
int val,ch[2],num,sz,fa;//权值,孩子,该权值个数,子树中所有权值个数,父亲
}T[maxn];
inline int newnode(int u,int fa,int num){
T[++cnt].fa=fa;T[cnt].val=u;//是cnt不是u QAQ
T[cnt].sz=1;T[cnt].num=num;
return cnt;
}
bool ident(int x){return lchild(fa(x))==x?0:1;}
void link(int x,int fa,int dir){T[fa(x)=fa].ch[dir]=x;}
void update(int x){
T[x].sz=T[lchild(x)].sz+T[rchild(x)].sz+1;}
void rotate(int x){
int dir=ident(x),Y=fa(x),Z=fa(Y);
link(T[x].ch[dir^1],Y,dir);
link(x,Z,ident(Y));
link(Y,x,dir^1);
update(Y);update(x);//此处要先更新Y再更新x,因为此时Y是x的孩子
}
void splay(int x,int to){//x==to也可以处理
to=fa(to);
while(fa(x)!=to){
if(fa(fa(x))==to)rotate(x);
else if(ident(x)==ident(fa(x))) rotate(fa(x)),rotate(x);
else rotate(x),rotate(x);
}
}
void insert(int x,int idx){//权重为x的,个数表示身份标识
if(!root) root=newnode(x,0,idx);
else{
int now=root;
while(1){
T[now].sz++;//T[now].sz+=idx;加个数
if(T[now].val==x){ T[now].num+=idx,splay(now,root);return;}
int dir=T[now].val<x?1:0;
if(!T[now].ch[dir]){
splay(T[now].ch[dir]=newnode(x,now,idx),root);
return;
}
now=T[now].ch[dir];
}
}
}
int get(int now,int dir){//now是点的编号,dir==0找前驱,dir==1找后继,此处是要找的now已经是根的情况下
//if(T[now].num>1) return T[now].val;//决定是否为找严格小于大于的前驱和后继(注释掉就是严格
now=T[now].ch[dir];
if(!now) return -1;
while(T[now].ch[dir^1]) now=T[now].ch[dir^1];
return T[now].val;
}
int find(int x){//找到key为x的编号
int now=root;
while(1){
if(T[now].val==x){ splay(now,root);return now;}
int dir=x<T[now].val?0:1;
if(!T[now].ch[dir]) return 0;
now=T[now].ch[dir];
}
}
void dele(int x){//删掉key为x的点
x=find(x);//注释掉这句就是删除编号为x的点啦
if(!x) return;
//if(T[x].num>1){T[x].num--;T[x].sum--;return ;}//决定是删掉该权值的一个点还是删掉权值的所有点
if(lchild(x)){
int pre=lchild(x);
while(rchild(pre)) pre=rchild(pre);
splay(pre,lchild(root));
link(rchild(root),pre,1);
link(pre,0,1);
update(pre);
}else{
root=rchild(x);
T[root].fa=0;
}
}
int kth(int k){//key第k大的点(key)的编号,不去重的哦,去重的话sz对每种key只记1即可
int now=root;
while(1){
int used=T[now].sz-T[rchild(now)].sz;
if(T[lchild(now)].sz<k&&k<=used){ splay(now,root);return now;}
if(k<used) now=lchild(now);
else now=rchild(now),k-=used;
}
}
int op,x,p,now;
int main(){
while(scanf("%d",&op)&&op){
if(op==1){
scanf("%d%d",&x,&p);
insert(p,x);//插入p,id为x
}else if(!root) printf("0\n");//树空输出0
else{
if(op==2){
now=kth(T[root].sz);
printf("%d\n",T[now].num);
}
else{
now=kth(1);
printf("%d\n",T[now].num);
}
dele(T[now].val);
}
}
return 0;
}
对模板的整理:
查询数x的排名:
int rak(int val){//查询key==val的数的排名
int pos=find(val);
return T[lchild(pos)].sz+1;
}
每次插入一个点:
inline int newnode(int u,int fa){
T[++cnt].fa=fa;T[cnt].val=u;
T[cnt].sz=T[cnt].num=1;//涉及sum&num
return cnt;
}
void update(int x){T[x].sz=T[lchild(x)].sz+T[rchild(x)].sz+T[x].num;}//涉及sum&num
void insert(int x,int idx){//权重为x的,插入idx个
if(!root) root=newnode(x,0,idx);
else{
int now=root;
while(1){
T[now].sz++;//涉及sum&num
if(T[now].val==x){ T[now].num++,splay(now,root);return;}//涉及sum&num
int dir=T[now].val<x?1:0;
if(!T[now].ch[dir]){
splay(T[now].ch[dir]=newnode(x,now,idx),root);
return;
}
now=T[now].ch[dir];
}
}
}
同时插入多个权值相同的点,num记录点的个数,sum为所有点的个数:
inline int newnode(int u,int fa,int num){
T[++cnt].fa=fa;T[cnt].val=u;
T[cnt].sz=T[cnt].num=num;//涉及sum&num
return cnt;
}
void update(int x){T[x].sz=T[lchild(x)].sz+T[rchild(x)].sz+T[x].num;}//涉及sum&num
void insert(int x,int idx){//权重为x的,插入idx个
if(!root) root=newnode(x,0,idx);
else{
int now=root;
while(1){
T[now].sz+=idx;//涉及sum&num
if(T[now].val==x){ T[now].num+=idx,splay(now,root);return;}//涉及sum&num
int dir=T[now].val<x?1:0;
if(!T[now].ch[dir]){
splay(T[now].ch[dir]=newnode(x,now,idx),root);
return;
}
now=T[now].ch[dir];
}
}
}