Splay Tree,重点在子树的旋转,线段树很难实现:
#include<iostream> #define DEBUG_ENABLE 1 using namespace std; #define MAXN 100005 #define KeyNode (ch[ch[root][1]][0]) int num[MAXN][2]; struct Pair{int v,i;}; struct SplayTree{ int sz[MAXN]; //sz[x]-x为根结点的结点数量 int ch[MAXN][2]; //ch[x][0]-x的左子节点;ch[x][1]-x的右子节点 int pre[MAXN]; //pre[x]-x的父结点 int root,top1,top2; //root-根结点;top1-未用结点队列头指针;top2-结点回收栈的栈顶指针 int ss[MAXN],que[MAXN]; /***********************************以下代码基本不变*********************************************/ /* Rotate(x,f):f=0-将x点左旋;f=1-将x点右旋 */ inline void rotate(int x,int f){ int y=pre[x]; push_down(y); push_down(x); ch[y][!f]=ch[x][f]; pre[ch[x][f]]=y; pre[x]=pre[y]; if(pre[y]) if(ch[pre[y]][0]==y) ch[pre[y]][0]=x; else ch[pre[y]][1]=x; ch[x][f]=y; pre[y]=x; push_up(y); } /* splay(x,goal):将x结点伸展为goal结点的子节点 */ inline void splay(int x,int goal){ for(push_down(x);pre[x]!=goal;){ // debug(); if(pre[pre[x]]==goal){ /* x节点的父结点的父结点为goal,进行单旋转 */ if(ch[pre[x]][0]==x) rotate(x,1); else rotate(x,0); } else{ int y=pre[x]; int z=pre[y]; if(ch[z][0]==y) if(ch[y][0]==x){ /* 一字形旋转 */ rotate(y,1); rotate(x,1); } else{ /* 之字形旋转 */ rotate(x,0); rotate(x,1); } else if(ch[y][1]==x){ /* 一字形旋转 */ rotate(y,0); rotate(x,0); } else{ /* 之字形旋转 */ rotate(x,1); rotate(x,0); } } push_up(x); if(goal==0) root=x; } } /* rotateTo(k,goal):将序列中第k个数转到goal的子节点 */ inline void rotateTo(int k,int goal){ /* 第k位要利用中序遍历来查找 */ int tmp,t; for(t=root;;){ push_down(t); /* 标记下延 */ tmp=sz[ch[t][0]]; if(k==tmp+1) break; if(k<=tmp) /* 第k个节点在t的左子树,向左遍历 */ t=ch[t][0]; else{ k-=tmp+1; t=ch[t][1]; } } splay(t,goal); } /* erase(x):把x为节点的子树删除,放到内存池 */ inline void erase(int x){ int head,tail; for(que[tail++]=x;head<tail;head++){ ss[top2++]=que[head]; if(ch[que[head]][0]) que[tail++]=ch[que[head]][0]; if(ch[que[head]][1]) que[tail++]=ch[que[head]][1]; } } /* getEnd(x,c): 得到x节点最边缘的节点 c=0-最左边的 c=1-最右边的 */ inline int getEnd(int x,int c){ while(ch[x][c]){ push_down(x); x=ch[x][c]; } return x; } /* getNear(x,c): 得到x节点最近的节点 c=0-前驱节点 c=1-后继节点 */ inline int getNear(int x,int c){ if(ch[x][c]){ return getEnd(ch[x][c],1-c); } while(pre[x]&&ch[pre[x]][c]==x) x=pre[x]; return pre[x]; } /* getSucc(x): 得到x节点的后继节点 */ inline int getSucc(int x) { return getNear(x,1); } /* getPrev(x): 得到x节点的前驱节点 */ inline int getPrev(int x) { return getNear(x,0); } /*****************************************END*********************************************/ /****************************************Debug*********************************************/ #if (DEBUG_ENABLE == 1) void debug() {printf("%d/n",root);Treaval(root);} void Treaval(int x) { if(x) { printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,_rev = %2d, val = %2d, index = %2d, minNode = %2d/n",x,ch[x][0],ch[x][1],pre[x],sz[x],_rev[x],val[x][0],val[x][1],minNode[x]); Treaval(ch[x][0]); Treaval(ch[x][1]); } } #endif /*****************************************END**********************************************/ /**/ inline void markNode(int x){ if(x){ _rev[x]=!_rev[x]; int tmp; tmp=ch[x][0];ch[x][0]=ch[x][1];ch[x][1]=tmp; } } /* push_down 把延迟标记推到孩子 */ inline void push_down(int x){ if(_rev[x]){ markNode(ch[x][0]); markNode(ch[x][1]); _rev[x]=false; } } /* push_up 把孩子的状态更新上来 */ inline void push_up(int x){ sz[x]=1+sz[ch[x][0]]+sz[ch[x][1]]; /* 题目的特定函数内容 */ minNode[x]=x; if(ch[x][0]&&isSmaller(minNode[ch[x][0]],minNode[x])) minNode[x]=minNode[ch[x][0]]; if(ch[x][1]&&isSmaller(minNode[ch[x][1]],minNode[x])) minNode[x]=minNode[ch[x][1]]; } /* To create a new node 题目不同,函数内容不同 */ inline void newNode(int &x,int m){ if(top2) x=ss[--top2]; else x=++top1; ch[x][0]=ch[x][1]=pre[x]=0; sz[x]=1; _rev[x]=false; minNode[x]=x; val[x][0]=num[m][0]; val[x][1]=num[m][1]; } /* To build a splay tree 题目不同,函数内容不同 */ inline void makeTree(int &x,int l,int r,int f){ if(l>r) return ; int m=(r+l)>>1; newNode(x,m); makeTree(ch[x][0],l,m-1,x); makeTree(ch[x][1],m+1,r,x); pre[x]=f; push_up(x); } /* Initial Function 题目不同,函数内容不同 */ inline void init(int n){ ch[0][0]=ch[0][1]=pre[0]=sz[0]=0; _rev[0]=false; root=top1=top2=0; num[0][0]=num[0][1]=0; /* 增加第一个边界结点 */ newNode(root,0); /* Read into the Datas */ int i; for(i=1;i<=n;i++){ scanf("%d",&num[i][0]); num[i][1]=i; } /* 增加第二个边界节点 */ num[n+1][0]=0x3fffffff; num[n+1][1]=0x3fffffff; makeTree(ch[root][1],1,n+1,root); push_up(root); } /* update 更新函数 题目不同内容不同 */ /* inline void update(){ int l,r,c; scanf("%d%d%d",&l,&r,&c); rotateTo(l,0); rotateTo(r+2,root); add[KeyNode]+=c; sum[KeyNode]+=(long long)c*sz[KeyNode]; } /* query 查询函数 题目不同内容不同 */ /* inline void query(){ int l,r; scanf("%d%d",&l,&r); rotateTo(l,0); rotateTo(r+2,root); printf("%I64d/n",sum[KeyNode]); } */ /* run() */ inline void run(int n){ int i; int min_node=1; int succ_node; for(i=0;i<n-1;i++){ splay(min_node,0); // debug(); // if(i==1) break; min_node=minNode[ch[root][1]]; // cout<<"min_node: "<<min_node<<endl; splay(min_node,root); // debug(); succ_node=getSucc(min_node); // cout<<"succ_node: "<<succ_node<<endl; splay(succ_node,root); printf("%d ",i+sz[ch[succ_node][0]]); markNode(ch[succ_node][0]); // debug(); } printf("%d/n",n); } /* isSmaller(a,b): a<b retrun 1*/ inline int isSmaller(int a,int b){ if(val[a][0]<val[b][0]) return 1; else if(val[a][0]==val[b][0]&&val[a][1]<val[b][1]) return 1; return 0; } /* Optional Variables 题目不同,变量不同 */ bool _rev[MAXN]; int val[MAXN][2]; int minNode[MAXN]; }spt; int main() { int n,m; while(scanf("%d",&n)&&n){ spt.init(n); // spt.debug(); spt.run(n); } return 0; }