bzoj 3223: Tyvj 1729 文艺平衡树

3223: Tyvj 1729 文艺平衡树

Time Limit: 10 Sec   Memory Limit: 128 MB
Submit: 2018   Solved: 1123
[ Submit][ Status][ Discuss]

Description

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 

Input

第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n)  m表示翻转操作次数
接下来m行每行两个数[l,r] 数据保证 1<=l<=r<=n 

Output

 

输出一行n个数字,表示原始序列经过m次变换后的结果 

Sample Input

5 3

1 3

1 3

1 4

Sample Output

4 3 2 1 5

HINT



N,M<=100000

Source


思路:
伸展树实现翻转

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

#define LS(x) node[(x)].ch[0]
#define RS(x) node[(x)].ch[1]

const int N = 1e5 + 5;

struct Splay {
	struct Node {
		int fa, ch[2];
		bool rev;
		int val, size;
		void init(int _val) {
			val = _val;
			size = 1;
			rev = ch[0] = ch[1] = 0;
		}
	} node[N];

	int root;

	void up(int x) {
		node[x].size = node[LS(x)].size + node[RS(x)].size + 1;
	}

	void rotate(int x, bool kind) {
		int fx = node[x].fa;
		int ffx = node[fx].fa;
		node[fx].ch[!kind] = node[x].ch[kind];
		node[node[x].ch[kind]].fa = fx;

		node[x].ch[kind] = fx;
		node[fx].fa = x;

		node[ffx].ch[RS(ffx) == fx] = x;
		node[x].fa = ffx;
		up(fx);
	}

	void down(int x) {
		if(x == 0) return ;
		if(node[x].rev) {
			if(LS(x)) node[LS(x)].rev ^= 1;
			if(RS(x)) node[RS(x)].rev ^= 1;
			swap(LS(x), RS(x));
			node[x].rev = 0;
		}
	}

	void splay(int x, int goal) {
		while(node[x].fa != goal) {
			int fx = node[x].fa;
			int ffx = node[fx].fa;
			down(ffx); down(fx); down(x);
			bool rot_x = (LS(fx) == x);
			bool rot_fx = (LS(ffx) == fx);
			if(ffx == goal) rotate(x, rot_x);
			else {
				if(rot_x == rot_fx) rotate(fx, rot_fx);
				else rotate(x, rot_x);
				rotate(x, rot_fx);
			}
		}
		up(x);
		if(goal == 0) root = x;
	}

	int select(int pos) {
		int u = root;
		down(u);
		while(node[LS(u)].size != pos) {
			if(pos < node[LS(u)].size)
				u = LS(u);
			else {
				pos -= node[LS(u)].size + 1;
				u = RS(u);
			}
			down(u);
		}
		return u;
	}

	void rev(int L, int R) {
		int u = select(L - 1), v = select(R + 1);
		splay(u, 0); splay(v, u);
		node[LS(v)].rev ^= 1;
	}

	int build(int L, int R) {
		if(L > R) return 0;
		if(L == R) return L;
		int mid = (L + R) >> 1;
		int r_L, r_R;
		LS(mid) = r_L = build(L, mid - 1);
		RS(mid) = r_R = build(mid + 1, R);
		node[r_L].fa = node[r_R].fa = mid;
		up(mid);
		return mid;
	}

	void init(int n) {
		node[0].init(0); node[0].size = 0;
		node[1].init(0);
		node[n + 2].init(0);
		for(int i = 2; i <= n + 1; ++i)
			node[i].init(i - 1);
		root = build(1, n + 2);
	}
	void print(int);
} splay;

int ans[N], tot;

void Splay :: print(int u) {
	if(u == 0) return ;
	down(u);
	print(LS(u));
	if(node[u].val)
		ans[tot++] = node[u].val;
	print(RS(u));
}

int main() {
	int n, m;
	scanf("%d%d", &n, &m);
	splay.init(n);
	for(int i = 0; i < m; ++i) {
		int u, v;
		scanf("%d%d", &u, &v);
		splay.rev(u, v);
	}
	splay.print(splay.root);
	for(int i = 0; i < tot; ++i) {
		printf("%d ", ans[i]);
	}
	puts("");
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值