平衡樹Splay
阿新 • • 發佈:2018-06-13
new roo conn #define i++ 順序 scan spl --
#include <cstdio> #define ls t[now].ch[0] #define rs t[now].ch[1] int min(int x,int y){return x<y?x:y;} int max(int x,int y){return x>y?x:y;} const int inf=0x3f3f3f3f; const int N=100010; struct Splay { int par,ch[2],dat,siz,cnt; }t[N]; int tot=0,root,t_size=0; int identity(int x)//是父親的左0/右1孩子 { return t[t[x].par].ch[0]==x?0:1; } void connect(int fa,int s,int typ)//建立父子關系 { t[fa].ch[typ]=s; t[s].par=fa; } void updata(int now) { t[now].siz=t[ls].siz+t[rs].siz+t[now].cnt; } void rotate(int p,int typ)//0左上旋,1右上旋 { int q=t[p].ch[typ];//要轉的兒子 connect(p,t[q].ch[typ^1],typ);//順序不能換,得註意一下 connect(t[p].par,q,identity(p)); connect(q,p,typ^1); updata(p),updata(q);//順序不能換 } void splay(int v,int u)//把v位置調整至u { u=t[u].par; while(t[v].par!=u) { int f=t[v].par,g=t[f].par; if(g==u||identity(v)!=identity(f)) rotate(f,identity(v)); else { rotate(g,identity(f)); rotate(f,identity(v)); } } } int New(int dat,int fa) { t[++tot].par=fa,t[tot].dat=dat,t[tot].cnt=1,t[tot].siz=1,t_size++; return tot; } void free(int x) { t[x].siz=0,t[x].dat=0,t[x].cnt=0,t[x].par=0,t[x].ch[0]=0,t[x].ch[1]=0; if(x==tot) tot--; } void insert(int dat) { if(!t_size) {root=New(dat,0);connect(0,tot,1);return;}//特判建虛根 int now=root,las; while(1) { int tpy=t[now].dat>dat?0:1; t[now].siz++; las=now; now=t[now].ch[tpy]; if(!now) { now=New(dat,las); t[las].ch[tpy]=now; break; } if(t[now].dat==dat) { t[now].cnt++; break; } } splay(now,root); root=now; } int find(int dat)//查找並調整 { int now=root; while(1) { if(t[now].dat==dat) { splay(now,root);//調整位置至根 root=now; return now; } int typ=t[now].dat>dat?0:1; now=t[now].ch[typ]; } } int g_max(int now) { return t[now].ch[1]?g_max(t[now].ch[1]):now; } void extrack(int dat) { int loc=find(dat);//找到刪除節點位置並伸展 if(t[loc].cnt>1) {t[loc].cnt--;t[loc].siz--;return;}//刪除一個值並更新 t_size--;//整棵樹的大小-- if(!t[root].ch[0]) {root=t[root].ch[1];return;}//左子樹空拿右子樹頂 loc=g_max(t[root].ch[0]);//找到左子樹最大值的位置 splay(loc,t[root].ch[0]);//把左子樹最大值伸展至根節點 connect(t[root].ch[0],t[root].ch[1],1);//建立聯系 loc=root;//記錄一下原根以便free root=t[root].ch[0];//更新根節點 connect(0,root,1);//與虛根建立關系 updata(root);//更新大小 free(loc);//釋放原根 } void get_rank(int x)//查詢x的排名 { root=find(x); printf("%d\n",t[t[root].ch[0]].siz+1); } void fget_rank(int x)//排名為x的數 { int now=root; while(1) { if(t[ls].siz<x&&x<=t[ls].siz+t[now].cnt) {printf("%d\n",t[now].dat);return;} else if(x>t[ls].siz+t[now].cnt) {x-=t[ls].siz+t[now].cnt;now=rs;} else now=ls; } } void get_pre(int x) { int m_max=-inf,now=root; while(now) { if(t[now].dat<x) {m_max=max(m_max,t[now].dat);now=rs;} else now=ls; } printf("%d\n",m_max); } void get_suc(int x) { int m_min=inf,now=root; while(now) { if(t[now].dat>x) {m_min=min(m_min,t[now].dat);now=ls;} else now=rs; } printf("%d\n",m_min); } int main() { int opt,x,n; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d%d",&opt,&x); if(opt==1) insert(x); else if(opt==2) extrack(x); else if(opt==3) get_rank(x);//查詢x的排名 else if(opt==4) fget_rank(x);//查詢排名為x的數 else if(opt==5) get_pre(x); else get_suc(x); } return 0; }
先放著...
平衡樹Splay