HDU 1890 Robotic Sort(Splay tree)

转载请注明出处,谢谢 http://blog.csdn.net/ACM_cxlove?viewmode=contents           by---cxlove

对区间有反转,同样用懒惰标记,SPT比较方便。

依次考虑第K大的,将其旋转至根,左子树的数量便是需要反转的,之后把根删除即可

难道是我的伸展函数有问题,一直TLE,注释部分的求大神解释。

换了一个Splay函数就过了。。。郁闷啊,debug到死

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define N 100015
#define inf 1<<29
#define LL long long
#define Key_value ch[ch[root][1]][0]
using namespace std;
int pre[N],ch[N][2],root,tot1;  //分别表示父结点,键值,左右孩子(0为左孩子,1为右孩子),根结点,结点数量
int size[N];    //分别表示子树规模,内存池,内存池容量
int rev[N];
int n,q;
inline void NewNode(int &r,int father,int k){
	r=k;
	pre[r]=father;
	rev[r]=0;
	size[r]=1;
	ch[r][0]=ch[r][1]=0;  //左右孩子为空
}
//将延迟标记更新到孩子结点
inline void Push_Down(int r){
	if(rev[r]){
		rev[ch[r][0]]^=1;
		rev[ch[r][1]]^=1;
		swap(ch[r][0],ch[r][1]);
		rev[r]=0;
	}
}
//通过孩子结点更新父结点
inline void Push_Up(int r){
	size[r]=size[ch[r][0]]+size[ch[r][1]]+1;
}
//旋转,kind为1为右旋,kind为0为左旋
inline void Rotate(int x,int kind){
	int y=pre[x];
	Push_Down(y);
	Push_Down(x);
	//类似SBT,要把其中一个分支先给父节点
	ch[y][!kind]=ch[x][kind]; 
	pre[ch[x][kind]]=y;
	//如果父节点不是根结点,则要和父节点的父节点连接起来
	pre[x]=pre[y];
	if(pre[x])
		ch[pre[y]][ch[pre[y]][1]==y]=x;
	ch[x][kind]=y;
	pre[y]=x;
	Push_Up(y);
}inline void zig(int x){
	int y=pre[x], z=pre[y];
	ch[y][1]=ch[x][0]; pre[ch[x][0]]=y;
	ch[x][0]=y; pre[y]=x;
	pre[x]=z;
	if(z) ch[z][ch[z][1]==y]=x;
	Push_Up(y);
}
inline void zag(int x){
	int y=pre[x], z=pre[y];
	ch[y][0]=ch[x][1]; pre[ch[x][1]]=y;
	ch[x][1]=y; pre[y]=x;
	pre[x]=z;
	if(z) ch[z][ch[z][1]==y]=x;
	Push_Up(y);
}
inline void zigzig(int x){
	int y=pre[x], z=pre[y], fz=pre[z];
	ch[z][1]=ch[y][0]; pre[ch[y][0]]=z;
	ch[y][1]=ch[x][0]; pre[ch[x][0]]=y;
	pre[z]=y; ch[y][0]=z;
	pre[y]=x; ch[x][0]=y;
	pre[x]=fz;
	if(fz) ch[fz][ch[fz][1]==z]=x;
	Push_Up(z); Push_Up(y);
}
inline void zagzag(int x){
	int y=pre[x], z=pre[y], fz=pre[z];
	ch[z][0]=ch[y][1]; pre[ch[y][1]]=z;
	ch[y][0]=ch[x][1]; pre[ch[x][1]]=y;
	pre[z]=y; ch[y][1]=z;
	pre[y]=x; ch[x][1]=y;
	pre[x]=fz;
	if(fz) ch[fz][ch[fz][1]==z]=x;
	Push_Up(z); Push_Up(y);
}
inline void zigzag(int x){
	int y=pre[x], z=pre[y], fz=pre[z];
	ch[y][1]=ch[x][0]; pre[ch[x][0]]=y;
	ch[z][0]=ch[x][1]; pre[ch[x][1]]=z;
	pre[y]=pre[z]=x;
	ch[x][0]=y; ch[x][1]=z;
	pre[x]=fz;
	if(fz) ch[fz][ch[fz][1]==z]=x;
	Push_Up(z); Push_Up(y);
}
inline void zagzig(int x){
	int y=pre[x], z=pre[y], fz=pre[z];
	ch[y][0]=ch[x][1]; pre[ch[x][1]]=y;
	ch[z][1]=ch[x][0]; pre[ch[x][0]]=z;
	pre[y]=pre[z]=x;
	ch[x][1]=y; ch[x][0]=z;
	pre[x]=fz;
	if(fz) ch[fz][ch[fz][1]==z]=x;
	Push_Up(z); Push_Up(y);
}
void Splay(int x, int goal){
	int y, z;
	Push_Down(x);
	while(pre[x]!=goal){
		if(pre[pre[x]]==goal){
			y=pre[x]; Push_Down(y); Push_Down(x);
			if(ch[y][1]==x) zig(x);
			else zag(x);
		}
		else{
			y=pre[x]; z=pre[y];
			Push_Down(z); Push_Down(y); Push_Down(x);
			if(ch[z][1]==y){
				if(ch[y][1]==x) zigzig(x);
				else zagzig(x);
			}
			else{
				if(ch[y][0]==x) zagzag(x);
				else zigzag(x);
			}
		}
	}
	Push_Up(x);
	if(pre[x]==0) root=x;
}
//Splay调整,将根为r的子树调整为goal
/*inline void Splay(int r,int goal){
	Push_Down(r);
	while(pre[r]!=goal){
		//父节点即是目标位置,goal为0表示,父节点就是根结点
		if(pre[pre[r]]==goal)
			Rotate(r,ch[pre[r]][0]==r);
		else{
			int y=pre[r];
			int kind=(ch[pre[y]][0]==y);
			//两个方向不同,则先左旋再右旋
			if(ch[y][kind]==r){
				Rotate(r,!kind);
				Rotate(r,kind);
			}
			//两个方向相同,相同方向连续两次
			else{
				Rotate(y,kind);
				Rotate(r,kind);
			}
		}
	}
	Push_Up(r);
	//更新根结点
	if(goal==0) root=r;
}
*/
inline int Get_Max(int r){  
	Push_Down(r);
	while(ch[r][1]){
		r=ch[r][1];
		Push_Down(r); 
	}
	return r;  
}  
inline void Remove(){ // erase the root
	if(ch[root][0]==0){
		root=ch[root][1];
		pre[root]=0;
	}
	else{
		int m=Get_Max(ch[root][0]);
			Splay(m,root);
		ch[m][1]=ch[root][1];
		pre[ch[root][1]]=m;
		root=m;
		pre[root]=0;
		Push_Up(root);
	}
}
inline void BulidTree(int &x,int l,int r,int father){
	if(l>r)
		return;
	int mid=(l+r)>>1;
	NewNode(x,father,mid);
	BulidTree(ch[x][0],l,mid-1,x);
	BulidTree(ch[x][1],mid+1,r,x);
	Push_Up(x);
}
 
struct Node{
	int idx,num;
}a[N];
inline bool cmp(Node n1,Node n2){
	return n1.num!=n2.num?n1.num<n2.num:n1.idx<n2.idx;
}
inline void Init(){
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i].num);
		a[i].idx=i;
	}
	sort(a+1,a+1+n,cmp);
	ch[0][0]=ch[0][1]=pre[0]=size[0]=rev[0]=0;
	root=tot1=0;
	BulidTree(root,1,n,0); 
}
int main(){
	while(scanf("%d",&n)!=EOF&&n){
		Init();
		for(int i=1;i<n;i++){		
			Splay(a[i].idx,0);
			rev[ch[root][0]]^=1;			
			printf("%d ",i+size[ch[root][0]]);			
			Remove();			
		}
		printf("%d\n",n);
	}
	return 0;
}


你可能感兴趣的:(struct,tree,ini,UP,n2)