1. 程式人生 > >3391 模板Splay

3391 模板Splay

以及 war truct pre 模板 for 增加 swap while

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define maxn 200000
  4 int read()
  5 {
  6     char ch=getchar();int f=1,w=0;
  7     while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
  8     while(ch<=9&&ch>=0){w=w*10+ch-0;ch=getchar();}
  9     return f*w;
 10 }
11 12 int n,root,m,tot; 13 14 struct sj 15 { 16 int ch[2]; //左兒子和右兒子 17 int ff,v; //ff是父親 v 18 int size; //size是兒子節點個數 19 int mark; //打上的標記 20 void init(int x,int fa) //初始化一個節點 左兒子和右兒子以及父親都清零 21 {
22 ff=ch[0]=ch[1]=0; 23 size=1;v=x;ff=fa; //含有子節點個數為1 父親節點為參數fa 24 } 25 }t[maxn]; 26 27 inline void pushup(int x) 28 { 29 t[x].size=t[t[x].ch[0]].size+t[t[x].ch[1]].size+1; 30
} 31 32 inline void pushdown(int x) 33 { 34 if(t[x].mark) 35 { 36 t[t[x].ch[0]].mark^=1; 37 t[t[x].ch[1]].mark^=1; 38 t[x].mark=0; 39 swap(t[x].ch[0],t[x].ch[1]); 40 } 41 } 42 43 inline void rotate(int x) //旋轉函數 44 { 45 int y=t[x].ff; 46 int z=t[y].ff; //這是爺爺節點 47 int k=t[y].ch[1]==x; //看x是左兒子還是右兒子 k取0,1 48 t[z].ch[t[z].ch[1]==y]=x; //這是把爺爺節點的左/右兒子變成x 49 t[x].ff=z; 50 t[y].ch[k]=t[x].ch[k^1]; 51 t[t[x].ch[k^1]].ff=y; 52 t[x].ch[k^1]=y; 53 t[y].ff=x; //此段畫圖理解 54 pushup(y);pushup(x); //再繼續進行修改 push_up(); 55 } 56 57 inline void splay(int x,int goal) 58 { 59 while(t[x].ff!=goal) //當我的這個節點還沒有達到目標位置 60 { 61 int y=t[x].ff;int z=t[y].ff; 62 if(z!=goal) //如果還沒有跳到目標節點 繼續旋轉 63 (t[z].ch[1]==y)^(t[y].ch[1]==x)?rotate(x):rotate(y); //Warning:: !!!!同邊現象時要先翻爸爸再翻兒子 否則不滿足搜索樹的性質!!!! 64 rotate(x); 65 } 66 if(goal==0)root=x; //如果目標節點是0 那麽就把root 根節點變成x 67 } 68 69 inline void insert(int x) 70 { 71 int u=root,ff=0; //從根節點開始插入 一開始父親變成0 72 while(t[u].size!=0)ff=u,u=t[u].ch[x>t[u].v]; //有根的時候 ff父親變成根節點 u再繼續下去向下操作 73 u=++tot; //tot是實時增加的一個記錄子節點個數的全局變量 74 if(ff)t[ff].ch[x>t[ff].v]=u; //如果父親不為零 他的父親的左/右兒子就是u 75 t[u].init(x,ff); //初始化這個節點 並且它的父親就是ff 76 splay(u,0); //把這個點旋轉到根節點 77 } 78 79 inline int get_k(int k) 80 { 81 int u=root; 82 while(1) 83 { 84 pushdown(u); 85 if(t[t[u].ch[0]].size>=k)u=t[u].ch[0]; 86 else if(t[t[u].ch[0]].size+1==k)return u; 87 else k-=t[t[u].ch[0]].size+1,u=t[u].ch[1]; 88 } 89 } 90 91 void write(int u) 92 { 93 pushdown(u); //最後輸出之前先push_down一遍 94 if(t[u].ch[0])write(t[u].ch[0]); //先讀左兒子 95 if(t[u].v>1&&t[u].v<n+2)printf("%d ",t[u].v-1); 96 if(t[u].ch[1])write(t[u].ch[1]); 97 } 98 99 inline void work(int l,int r) //工作函數 100 { 101 l=get_k(l); 102 r=get_k(r+2); 103 splay(l,0); 104 splay(r,l); 105 t[t[t[root].ch[1]].ch[0]].mark^=1; 106 } 107 108 int main() 109 { 110 n=read();m=read(); //n個點 m次翻轉 111 for(int i=1;i<=n+2;++i)insert(i); //跳過建樹 直接插入即可 再繼續看insert() 112 for(int i=1;i<=m;i++) 113 { 114 int l=read(),r=read(); 115 work(l,r); //工作函數 116 } 117 write(root); //輸出; 118 return 0; //大工告吉 119 }

3391 模板Splay