排序机械臂

link

题意是:写一个数据结构,支持区间翻转,支持查找元素位次,支持删除。这就是平衡树的板子嘛,而且甚至没有插入操作。这就好办啦,我写的是splay,最近重拾平衡树代码也打得愈发顺手了……

鉴于昨天打维护序列打崩溃,总结一下关于区间翻转的几个重要的点。一个是在调用任何节点时(特别是find)一定要先一路pushdown下来,不然查找的值肯定是错误的;即使是查找元素位次的操作也是需要先pre一下,把根到自己的一路全部pushdown了之后才能安安心心查询。delete函数在把x旋转下去的时候也是需要pushdown的。

其它没什么。要对当前元素是否是最后一个特殊处理,否则可能找不到相邻元素然后死掉。

写得挺顺。记了个时38分钟,一节课吧。

code

//begin at 20:10

#include<bits/stdc++.h>
//#define zczc
const int N=100010;
using namespace std;
inline void read(int &wh){
    wh=0;int f=1;char w=getchar();
    while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
    while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
    wh*=f;return;
}
inline void swap(int &s1,int &s2){
	int s3=s1;s1=s2;s2=s3;return;
}

int m,aa[N];
struct point{
	int data,pl;
}a[N];
inline bool cmp(point s1,point s2){
	return s1.data==s2.data?s1.pl<s2.pl:s1.data<s2.data;
}

#define lc t[x].ch[0]
#define rc t[x].ch[1]
struct node{
	int f,ch[2],size;
	bool lazy;
}t[N];
int root;

inline void pushup(int x){
	if(x==0)printf("error\n");
	t[x].size=t[lc].size+t[rc].size+1;
}
inline void pushnow(int x){
	t[x].lazy=t[x].lazy^1;
	swap(lc,rc);
}
inline void pushdown(int x){
	if(t[x].lazy){
		t[x].lazy=false;
		pushnow(lc);pushnow(rc);
	}
}

int build(int l,int r,int fa){
	if(l>r)return 0;
	if(l==r)return t[l].size=1,t[l].f=fa,l;
	int x=l+r+1>>1;t[x].f=fa;
	lc=build(l,x-1,x);rc=build(x+1,r,x);
	pushup(x);return x;
}
inline int work(int x,int from){
	return (from==rc?t[lc].size+1:0)+(t[x].f?work(t[x].f,x):0);
}
inline int find(int x,int kk){
	pushdown(x);
	if(t[lc].size>=kk)return find(lc,kk);
	if(t[lc].size+1==kk)return x;
	return find(rc,kk-t[lc].size-1);
}
inline void rotate(int x){
	int y=t[x].f;int z=t[y].f;
	int kk=t[y].ch[1]==x;int cd=t[x].ch[kk^1];
	if(z)t[z].ch[t[z].ch[1]==y]=x;t[x].f=z;
	t[cd].f=y;t[y].ch[kk]=cd;
	t[x].ch[kk^1]=y;t[y].f=x;
	if(y==root)root=x;
	pushup(y);pushup(x);return;
}
inline void splay(int x,int rt){
	while(t[x].f^rt){
		int y=t[x].f;int z=t[y].f;
		if(z^rt)(t[z].ch[1]==y)^(t[y].ch[1]==x)?rotate(x):rotate(y);
		rotate(x);
	}
	if(rt==0)root=x;
}

void pre(int x){
	if(t[x].f)pre(t[x].f);
	pushdown(x);
}
void delete_(int x){
	while(lc!=0||rc!=0){
		pushdown(x);
		if(lc&&rc)t[lc].size<t[rc].size?rotate(rc):rotate(lc);
		else if(lc)rotate(lc);
		else rotate(rc);
	}
	int fa=t[x].f;t[fa].ch[t[fa].ch[1]==x]=0;x=fa;
	while(x)pushup(x),x=t[x].f;
	return;
}

void print(int x){
	if(!x)return;
	pushdown(x);
	printf("%d %d %d&%d %d\n",x,t[x].size,lc,rc,t[x].f);
	print(lc);print(rc);
}
#undef lc
#undef rc

signed main(){
	
	#ifdef zczc
	freopen("in.txt","r",stdin);
	#endif
	
	srand(time(0));
	read(m);
	for(int i=1;i<=m;i++){
		read(a[i].data);a[i].pl=i;
		aa[i]=a[i].data;
	}
	sort(a+1,a+m+1,cmp);
	root=build(1,m,root);
	//print(root);printf("\n");
	
	for(int i=1;i<=m;i++){
		int x=a[i].pl,rk;pre(x);
		printf("%d ",(rk=work(x,t[x].ch[1]))+i-1);
		//rk=work(x,t[x].ch[1]); 
		if(rk==t[root].size){
			splay(x,0);pushnow(x);
		}
		else{
			int y=find(root,rk+1);
			//printf("x=%d y=%d\n",x,y);
			splay(y,0);splay(x,y);
			pushnow(x);
		}
		
		delete_(x);
		//print(root);printf("\n");
	}
	
	return 0;
}

//finish at 20:48
posted @ 2022-07-03 22:06  Feyn618  阅读(22)  评论(0编辑  收藏  举报