BZOJ 3223 文艺平衡树 【Splay】

本文介绍了一种使用C++模板元编程技术来实现翻转操作的方法,通过重载new运算符来避免动态内存分配。文章详细阐述了结构体Node的定义及其成员函数的实现,包括cmp、maintain、pushdown、operator new等,展示了如何在不使用额外内存的情况下进行元素的翻转。此外,还介绍了初始化函数Init、中序遍历函数MidOrder以及主函数main的实现逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

flip是个翻转标记辣 用重载的new可以不用再去动态开辟了

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cctype>
using namespace std;

const int Maxn(100005);

int n,m;

struct Node *null,*pt;
struct Node
{
	Node *ch[2];
	int v,s;
	bool flip;
	Node (int __ = 0) : v(__),s(1),flip(false)
	{
		ch[0] = ch[1] = null;
	}
	int cmp(int k) const 
	{
		k -= ch[0] -> s;
		if (k == 1) return -1;
		return k <= 0 ? 0 : 1;
	}
	void maintain()
	{
		s = ch[0] -> s + ch[1] -> s + 1; 
	}
	void pushdown()
	{
		if (flip)
		{
			flip = false;
			swap(ch[0],ch[1]);
			ch[0] -> flip ^= 1;
			ch[1] -> flip ^= 1;
		}
	}
	void *operator new (size_t) { return pt++; }
	
}*Root,N[Maxn],Null;


inline long long Read()
{
	long long Ret = 0;
	char c = getchar();
	while (!isdigit(c)) c = getchar();
	while (isdigit(c)) { Ret = Ret * 10 + c - '0'; c = getchar(); }
	return Ret;
}

inline void Rotate(Node *&o,const int &d)
{
	Node *k = o -> ch[d ^ 1]; o -> ch[d ^ 1] = k -> ch[d]; k -> ch[d] = o;
	o -> maintain(); k -> maintain(); o = k; 
}

void Splay (Node *&o,int k)
{
	o -> pushdown();
	int d = o -> cmp(k);
	if (d == 1) k -= o -> ch[0] -> s + 1;
	if (d != -1)
	{
		Node *p =  o -> ch[d];
		p -> pushdown();
		int d2 = p -> cmp(k);
		int k2 = d2 ? k - p -> ch[0] -> s - 1 : k;
		if (d2 != -1)
		{
			Splay(p -> ch[d2],k2);
			d == d2 ? Rotate(o,d ^ 1) : Rotate(o -> ch[d],d); 
		}
		Rotate(o,d ^ 1);
	}
}

Node *Build (int l,int r)
{
	if (l >= r) return null;
	int m = (l + r) >> 1;
	Node *o = new Node (m);
	if (l < m) o -> ch[0] = Build(l,m);
	if (m + 1 < r) o -> ch[1] = Build(m + 1,r);
	o -> maintain();
	return o;
}

void Init()
{
	pt = N; null = &Null; null -> s = 0;Root = Build(0,n + 2);
}


void MidOrder(Node *Root)
{
	if (Root == null) return ;
	Root -> pushdown();
	MidOrder(Root -> ch[0]);
	if (Root -> v >= 1 && Root -> v <= n) cout << Root -> v << ' ';
	MidOrder(Root -> ch[1]);
}

int main()
{
	freopen("input.txt","r",stdin);
	freopen("output.txt","w",stdout); 
	n = Read(); m = Read();
	Init();
	while (m--)
	{
		int l,r;
		cin >> l >> r;
		if (l == r) continue;
		Splay(Root,l);
		Splay(Root -> ch[1],r + 1 - Root -> ch[0] -> s);
		Root -> ch[1] -> ch[0] -> flip ^= 1;
	}
	MidOrder(Root);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值