求助splay
查看原帖
求助splay
307940
aaaaaaaawsl楼主2022/10/14 20:13
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

inline int read(){
	register int x = 0, f = 1; register char ch;
	for(; ch > '9' || ch < '0'; ch = getchar()) if(ch == '-') f = -1;
	for(; ch <= '9' && ch >= '0'; ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ '0'); 
	return x * f;
}

const int N = 8e4 + 10;

int t[N][2];//左右儿子 
int n, tot;
int val[N], fa[N];
int cnt[N], size[N];
int rt;
int pos[N];

void updata(int x){
	size[x] = size[t[x][0]] + size[t[x][1]] + 1;// 左加右加自身 
//	pos[val[t[x][0]]] = t[x][0]; pos[val[t[x][1]]] = t[x][1];
} 

void rot(int x){
	int y = fa[x], z = fa[y], k = (t[y][1] == x), w = t[x][k ^ 1]; // k为x在y的儿子位置,w为x的另一位置的儿子 
	if(z) t[z][t[z][1] == y] = x; fa[x] = z; //如果有爷爷,爸爸所在的位置被x替代,x的父亲变成z
	fa[fa[t[t[x][k ^ 1] = y][k] = w] = y] = x; //  1.x为y左儿子说明y应该在x左边右儿子反之,所以k^1,此时替代了w;2.x是y的左儿子说明x包括子树点权都小于y应该是y的左儿子,反之易得,所以k;3.fa[w] = y;4.fa[y] = x;
	updata(y); updata(x); // 先把y(x子树)upd再updx; 
}

void SPY(int x, int ps){// 把x转到pos的直接儿子 
	while(fa[x] != ps){
		int y = fa[x], z = fa[y]; // 爸爸,爷爷
		if(z != ps) rot((t[z][1] == y) ^ (t[y][1] == x) ? x : y); // 在z不是pos的时候(如果是会转走)看看xyz是否是直线(相同为0不同为1)是的话转y不是的话转x
		rot(x); //x一定转一次 
	}
//	pos[val[x]] = x;
	if(!ps) rt = x; //父亲为0即根; 
}

void insert(int w){ // 插入w
	int x = rt, y = 0; // x为当前找到的点, y为他的父亲
	while(t[rt][1]) x = t[rt][1];
	fa[++ tot] = x; t[x][1] = tot; val[tot] = w; pos[w] = tot, size[tot] = 1;
	SPY(tot, 0);
}

inline void ist_top(int w){
	SPY(pos[w], 0);
	if(!t[rt][0]) return;
	if(!t[rt][1]) t[rt][1] = t[rt][0], t[rt][0] = 0;
	else{
		int x = t[rt][1]; while(t[x][0]) x = t[x][0];
		fa[t[rt][0]] = x; t[x][0] = t[rt][0]; t[rt][0] = 0;
		SPY(t[x][0], 0);
	}
}

inline void ist_bottom(int w){
	SPY(pos[w], 0);
	if(!t[rt][1]) return;
	if(!t[rt][0]) t[rt][0] = t[rt][1], t[rt][1] = 0;
	else{
		int x = t[rt][0]; while(t[x][1]) x = t[x][1];
		fa[t[rt][1]] = x; t[x][1] = t[rt][1]; t[rt][1] = 0;
		SPY(t[x][1], 0);
	}
}

void in_pos(int w, int tt){
	SPY(pos[w], 0);
	if(!tt) return;
	if(tt == 1){
		int x = t[rt][1]; while(t[x][0]) x = t[x][0];
		int ps = pos[w];
		swap(pos[w], pos[val[x]]);
		swap(val[ps], val[x]);
	}
	else{
		int x = t[rt][0];
		while(t[x][1]) 
		x = t[x][1];
		int ps = pos[w];
		swap(pos[w], pos[val[x]]);
		swap(val[ps], val[x]);
	}
}

int query(int w){
	int x = rt; 
	while(1){
		if(size[t[x][0]] + 1 == w) return val[x];
		else if(size[t[x][0]] >= w) x = t[x][0];
		else w -= size[t[x][0]] + 1, x = t[x][1];
	}
}

int m;
char st[10];

int main(){
	n = read(); m = read();
	for(int i = 1; i <= n; ++ i){
		int a = read();
		insert(a);
	}
	
	for(int i = 1; i <= m; ++ i){
		std :: cin >> st;
		if(st[0] == 'T'){
			int a = read();
			ist_top(a);
		}
		else if(st[0] == 'B'){
			int a = read();
			ist_bottom(a);
		}
		else if(st[0] == 'I'){
			int a = read(), b = read();
			in_pos(a, b);
		}
		else if(st[0] == 'A'){
			int a = read();
			SPY(pos[a], 0);
			printf("%d\n", size[t[pos[a]][0]]);
			
		}
		else if(st[0] == 'Q'){
			int a = read();
			printf("%d\n", query(a));
		}
	}
}
/*
10 10
1 3 2 7 5 8 10 4 9 6
Query 3
Top 5
Ask 6
Bottom 3
Ask 3
Top 6
Insert 4 -1
Query 5
Query 2
Ask 2
*/

1.这份代码里pos的真正意义是什么

2.是根据什么建的平衡树

2022/10/14 20:13
加载中...