锰锌裘注Splay
查看原帖
锰锌裘注Splay
307453
云浅知处はなび楼主2020/10/13 13:01

准备去搞一搞 LCT,听说需要 Splay 前置知识,先回来打了一发 Splay 复习一下。

结果似乎 RE 了的样子。。

输出全部正确,不过最后会 RE 一下qwq......

其实很久以前我打的 Splay 也出现过这个问题

然后东改改西改改玄学正确了就没管它

#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cctype>

#define MAXN 100005
#define int long long

using namespace std;

struct Node{
	int ch[2],val,size,num,father;
	Node(int l,int r,int v,int s,int n,int f){
		ch[0]=l,ch[1]=r,val=v,size=s,num=n,father=f;
	}
	Node(){}
};

int rt,cnt;

struct Splay{

	Node t[MAXN];

	inline void pushup(int o){
		t[o].size=t[t[o].ch[0]].size+t[t[o].ch[1]].size+t[o].num;
	}

	inline void clear(int o){
		t[o]=Node(0,0,0,0,0,0);
	}

	inline bool get(int o){
		return o==t[t[o].father].ch[1];
	}

	inline void rotate(int o){
		int x=t[o].father,y=t[x].father;
		int r=get(o);
		t[x].ch[r]=t[o].ch[r^1];
		t[t[o].ch[r^1]].father=x;
		t[o].ch[r^1]=x;
		t[x].father=o;
		t[o].father=y;
		if(y)t[y].ch[x==t[y].ch[1]]=o;
		pushup(o);
		pushup(x);
	}

	inline void splay(int o){
		for(int f=t[o].father;f=t[o].father,f;rotate(o)){
			if(t[f].father)rotate(get(o)==get(f)?f:o);
		}
		rt=o;
	}

	inline void insert(int x){
		if(!rt){
			t[rt=++cnt].val=x;
			t[cnt].num++;
			pushup(rt);
			return ;
		}
		int cur=rt,f=0;
		while(1){
			if(t[cur].val==x){
				t[cur].num++;
				pushup(cur);
				pushup(f);
				splay(cur);
				break;
			}
			f=cur;
			cur=t[cur].ch[t[cur].val<x];
			if(!cur){
				t[rt=++cnt].val=x;
				t[cnt].num++;
				t[cnt].father=f;
				t[f].ch[t[f].val<x]=cnt;
				pushup(cnt);
				pushup(f);
				splay(cnt);
				break;
			}
		}
	}

	inline int rnk(int x){
		int ans=0,cur=rt;
		while(1){
			if(x<t[cur].val){
				cur=t[cur].ch[0];
			}
			else{
				ans+=t[t[cur].ch[0]].size;
				if(x==t[cur].val){
					splay(cur);
					return ans+1;
				}
				ans+=t[cur].num;
				cur=t[cur].ch[1];
			}
		}
	}

	inline int kth(int x){
		int cur=rt;
		while(1){
			if(t[cur].ch[0]&&x<=t[t[cur].ch[0]].size){
				cur=t[cur].ch[0];
			}
			else{
				x-=t[t[cur].ch[0]].size+t[cur].num;
				if(x<=0){
					splay(cur);
					return t[cur].val;
				}
				cur=t[cur].ch[1];
			}
		}
	}

	inline int pre(){
		int cur=t[rt].ch[0];
		while(t[cur].ch[1])cur=t[cur].ch[1];
		splay(cur);
		return cur;
	}

	inline int nxt(){
		int cur=t[rt].ch[1];
		while(t[cur].ch[0])cur=t[cur].ch[0];
		splay(cur);
		return cur;
	}

	inline void del(int x){
		rnk(x);
		if(t[rt].num>1){
			t[rt].num--;
			pushup(rt);
			return ;
		}
		if(!t[rt].ch[0]&&!t[rt].ch[1]){
			clear(rt);
			rt=0;
			return ;
		}
		if(!t[rt].ch[0]){
			int cur=rt;
			rt=t[rt].ch[1];
			t[rt].father=0;
			clear(cur);
			return ;
		}
		if(!t[rt].ch[1]){
			int cur=rt;
			rt=t[rt].ch[0];
			t[rt].father=0;
			clear(cur);
		}
		int cur=rt;
		int k=pre();
		splay(x);
		t[t[cur].ch[1]].father=k;
		t[k].ch[1]=t[cur].ch[1];
		clear(cur);
		pushup(rt);
	}

};

Splay tree;

signed main(void){

	int n,opt,x;
	scanf("%lld",&n);
	while(n--){
		scanf("%lld%lld",&opt,&x);
		if(opt==1){
			tree.insert(x);
		}
		else if(opt==2){
			tree.del(x);
		}
		else if(opt==3){
			printf("%lld\n",tree.rnk(x));
		}
		else if(opt==4){
			printf("%lld\n",tree.kth(x));
		}
		else if(opt==5){
			tree.insert(x);
			printf("%lld\n",tree.t[tree.pre()].val);
			tree.del(x);
		}
		else if(opt==6){
			tree.insert(x);
			printf("%lld\n",tree.t[tree.nxt()].val);
			tree.del(x);
		}
	}

	return 0;
}

对于很多数据,程序输出完正确输出数据之后终端都会显示一个 zsh: segmentation fault /kk

求大佬帮忙看看/kel

2020/10/13 13:01
加载中...