code[VS]1743反转卡片 SPlay

本文介绍了一种基于SPlay树的数据结构实现方法,重点在于处理区间翻转操作。通过添加虚拟节点避免了边界问题,并详细展示了旋转、下推等核心操作的实现细节。

弟弟救我。

原本想今晚不来机房的,结果硬生生写了个平衡树再回去。


SPlay区间翻转,为了防止越界可以在最后面增加一个虚拟节点。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>

#define INF 1<<30
#define N 600050

using namespace std;

int siz[N],tr[N],s[N][2],tag[N],fa[N];
int a[N],rt,cnt,n;

inline void update(int t) { siz[t] = siz[ s[t][0] ] + siz[ s[t][1] ] + 1; }

void rotate(int x,int &k) {
	int y = fa[x] , z = fa[y] , l = s[y][0] != x , r = l ^ 1;
	if (y == k) k = x; else {
		if (s[z][0] == y) s[z][0] = x; else s[z][1] = x; }
	fa[x] = z; fa[y] = x; fa[ s[x][r] ] = y;
	s[y][l] = s[x][r]; s[x][r] = y;
	update(y); update(x);
}

void SPlay(int x) {
	while (x != rt) {
		int y = fa[x] , z = fa[y];
		if (y != rt) {
			if ((s[z][0] == y)^(s[y][0] == x)) 
				rotate(x,rt);
			else
				rotate(y,rt);
		} 
		rotate(x,rt);
	}
}

inline void push_down(int t) {
	if (!tag[t]) return ;
	swap(s[t][0],s[t][1]);
	tag[ s[t][0] ] ^= 1;
	tag[ s[t][1] ] ^= 1;
	tag[t] ^= 1;
}

int kth(int k,int x) {
	push_down(x);
	int tmp = siz[ s[x][0] ] + 1;
	if (tmp == k) return x;
	return tmp > k ? kth(k,s[x][0]) : kth(k-tmp,s[x][1]);
}


void build(int l,int r,int &t,int f) {
	//if (l > r) return ;
	int mid = (l + r) >> 1;
	tr[ t=++cnt ] = mid;
	fa[t] = f;
	siz[t] = 1;
	if (l == r) return ;
	if (l <= mid-1) build(l,mid-1,s[t][0],t);
	if (mid+1 <= r) build(mid+1,r,s[t][1],t);
	update(t);
}

inline void solve() {
	build(1,n,rt,0);
	int tmp = 0 , ans = 0 , deb = 0;
	while (( tmp = a[ tr[ deb = kth(1,rt) ] ] ) != 1) {
		SPlay(deb);
		int p = kth(tmp+1,rt);
		SPlay(p);
		tag[ s[rt][0] ] ^= 1;
		ans++;
	}
	printf("%d\n",ans);
}

inline void init() {
	scanf("%d",&n);
	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
	a[++n] = INF;
}

int main()
{
	init();
	solve();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值