洛谷P3369-----普通平衡樹
阿新 • • 發佈:2018-12-12
洛谷上的一道splay水題
但是不知為何做了很長時間
甚至還動用了洛谷的樣例,可以說是非常菜了
跟正常的splay模版一樣
但是有點細節需要注意
求前驅和字尾的方式十分巧妙,但是必須要求的是如果一個元素沒有了,就必須讓他的節點消失,
而不是把個數改成0就可以了,否則找到的當前這個點如果沒有個數的話,可能是不如左子樹的元素的
還有注意不僅insert後要splay到根,query過後也要到跟,防止深度過長導致時間複雜度驟升
嗯,就是這樣
順帶一提這次noip差點退役,最後好死賴活著想繼續省選
現在估計是省選的人裡面最菜的一個了,唉。。。。。。
繼續努力吧
#include<bits/stdc++.h> using namespace std; const int base=1e7+7; struct node { node *son[2],*father; int size,num,cnt; }pool[3200005],*tail=pool,*root,*zero; int n,shu1,shu2,all; void update(node *nd) { nd->size=nd->son[0]->size+nd->son[1]->size+nd->cnt; } void rotate(node *nd) { node *p=nd->father; node *pp=p->father; int r1=p->son[0]==nd; int r2=pp->son[1]==p; node *s=nd->son[r1]; if(pp==zero) root=nd; else pp->son[r2]=nd; nd->father=pp; p->father=nd; nd->son[r1]=p; if(s!=zero) s->father=p; p->son[!r1]=s; update(p); update(nd); } void splay(node *nd,node *top) { while(nd->father!=top) { node *p=nd->father; if(p->father==top) { rotate(nd); } else { node *pp=p->father; if((pp->son[1]==p)==(p->son[1]==nd)) { rotate(p); rotate(nd); } else { rotate(nd); rotate(nd); } } } } void init() { zero=tail++; zero->son[0]=zero->son[1]=zero->father=zero; root=tail++; root->son[0]=tail++; root->son[1]=zero; root->son[0]->son[0]=zero; root->son[0]->son[1]=zero; root->size=2; root->cnt=1; root->num=1e7+5; root->son[0]->size=1; root->son[0]->cnt=1; root->son[0]->num=-1e7-5; root->son[0]->father=root; root->father=zero; } node *find_pos(int x) { node *pos=root; while(233) { if(x<pos->num) pos=pos->son[0]; else if(x>pos->num) pos=pos->son[1]; else return pos; } } node *find_num(int x) { x++; node *pos=root; while(233) { if(x<=pos->son[0]->size) pos=pos->son[0]; else if(x>pos->son[0]->size+pos->cnt) x-=pos->son[0]->size+pos->cnt,pos=pos->son[1]; else return pos; } } void print(node *nd) { if(nd==zero) return; print(nd->son[0]); for(int i=1;i<=nd->cnt;i++) printf("%d ",nd->num); print(nd->son[1]); } void insert(node *&nd,node *fa,int num) { if(nd==zero) { nd=tail++; nd->father=fa; nd->son[0]=nd->son[1]=zero; nd->size=1; nd->cnt=1; nd->num=num; splay(nd,zero); return; } if(num<nd->num) insert(nd->son[0],nd,num); else if(num>nd->num) insert(nd->son[1],nd,num); else {nd->cnt++;nd->size++;return;} update(nd); } int query_pos(int x) { node *pos=root; int ans=0; while(233) { if(x<pos->num) pos=pos->son[0]; else if(x>pos->num) ans+=pos->size-pos->son[1]->size,pos=pos->son[1]; else { ans+=pos->son[0]->size; splay(pos,zero); return ans; } } } int query_num(int x) { node *one=find_num(x); splay(one,zero); return one->num; } void dilit(int x) { node *one=find_pos(x); if(one->cnt==1) { int two=query_pos(x); node *r1=find_num(two-1); node *r2=find_num(two+1); splay(r1,zero); splay(r2,r1); r2->son[0]=zero; one=zero; update(r2); update(r1); } else { splay(one,zero); one->cnt--; one->size--; } } int pre(int x) { int ans=-0x7fffffff; node *pos=root; while(233) { if(pos->num<x&&pos->num>ans&&pos->cnt) ans=pos->num; if(x>pos->num) pos=pos->son[1]; else pos=pos->son[0]; if(pos==zero) { if(pos->father!=zero) splay(pos->father,zero); break; } } return ans; } int suf(int x) { int ans=0x7fffffff; node *pos=root; while(233) { if(pos->num>x&&pos->num<ans&&pos->cnt) ans=pos->num; if(x<pos->num) pos=pos->son[0]; else pos=pos->son[1]; if(pos==zero) { if(pos->father!=zero) splay(pos->father,zero); break; } } return ans; } int main() { init(); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d%d",&shu1,&shu2); if(shu1==1) { insert(root,zero,shu2); all++; } else if(shu1==2) { dilit(shu2); all--; } else if(shu1==3) { printf("%d\n",query_pos(shu2)); } else if(shu1==4) { printf("%d\n",query_num(shu2)); } else if(shu1==5) { printf("%d\n",pre(shu2)); } else if(shu1==6) { printf("%d\n",suf(shu2)); } } return 0; } /* 4 1 2 2 2 1 2 3 2 */