hdoj 3487 Play with Chain

splay模板题目一道,收录于此

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>
#include <map>
#include <string>
#include <climits> 
#include <set>
#include <string> 
#include <sstream>
#include <utility>
#include <ctime>
//#pragma comment(linker, "/STACK:1024000000,1024000000") 

using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::istringstream;
using std::getline;
using std::make_pair;
using std::greater;

const int MAXN(300010);
int N;

struct SPLAY_TREE
{
	struct NODE 
	{
		int num;
		int size;
		int reverse;
		NODE *fa;
		NODE *ch[2];
	};

	NODE *root, *NIL, *rear;
	NODE pool[MAXN];
	bool print_s;
	
	void newnode(NODE *&sour, NODE *f, int tn)
	{
		rear->num = tn;
		rear->size = 1;
		rear->fa = f;
		rear->ch[0] = rear->ch[1] = NIL;
		sour = rear++;
	}

	void push_up(NODE *sour)
	{
		sour->size = sour->ch[0]->size+sour->ch[1]->size+1;
	}

	void push_down(NODE *sour)
	{
		if(sour->reverse)
		{
			sour->ch[0]->reverse ^= 1;
			sour->ch[1]->reverse ^= 1;
			swap(sour->ch[0], sour->ch[1]);
			sour->reverse = 0;
		}
	}

	void init()
	{
		NIL = pool;
		rear = pool+1;
		NIL->num = -1;
		NIL->size = 0;
		NIL->fa = NIL->ch[0] = NIL->ch[1] = NIL;
		newnode(root, NIL, -1);
		newnode(root->ch[1], root, -1);
		build_tree(root->ch[1]->ch[0], root->ch[1], 1, N);
	}

	void build_tree(NODE *&sour, NODE *f, int l, int r)
	{
		if(l > r)
			return;
		int m = (l+r) >> 1;
		newnode(sour, f, m);
		build_tree(sour->ch[0], sour, l, m-1);
		build_tree(sour->ch[1], sour, m+1, r);
		push_up(sour);
	}

	void rotate(NODE *sour, int flag)
	{
		NODE *f = sour->fa;
		push_down(f);
		push_down(sour);
		f->ch[!flag] = sour->ch[flag];
		sour->ch[flag]->fa = f;
		sour->fa = f->fa;
		if(f->fa != NIL)
			f->fa->ch[f->fa->ch[1] == f] = sour;
		sour->ch[flag] = f;
		f->fa = sour;
		push_up(f);
	}

	void splay(NODE *sour, NODE *goal)
	{
		push_down(sour);
		while(sour->fa != goal)
		{
			if(sour->fa->fa == goal)
				rotate(sour, sour->fa->ch[0] == sour);
			else
			{
				NODE *f = sour->fa;
				int flag = (f->fa->ch[0] == f);
				if(f->ch[flag] == sour)
					rotate(sour, !flag);
				else
					rotate(f, flag);
				rotate(sour, flag);
			}
		}
		push_up(sour);
		if(goal == NIL)
			root = sour;
	}

	NODE *select(NODE *sour, int r)
	{
		push_down(sour);
		while(sour != NIL && sour->ch[0]->size+1 != r)
		{
			if(r <= sour->ch[0]->size)
				sour = sour->ch[0];
			else
			{
				r -= sour->ch[0]->size+1;
				sour = sour->ch[1];
			}
			push_down(sour);
		}
		return sour;
	}

	void CUT(int a, int b, int c)
	{
		NODE *p1, *p2, *p3;
		p1 = select(root, a);
		p2 = select(root, b+2);
		splay(p1, NIL);
		splay(p2, root);
		p3 = p2->ch[0];
		p2->ch[0] = NIL;
		splay(p2, NIL);
		p1 = select(root, c+1);
		p2 = select(root, c+2);
		splay(p1, NIL);
		splay(p2, root);
		p2->ch[0] = p3;
		p3->fa = p2;
		splay(p2, NIL);
	}

	void FLIP(int a, int b)
	{
		NODE *p1, *p2;
		p1 = select(root, a);
		p2 = select(root, b+2);
		splay(p1, NIL);
		splay(p2, root);
		p2->ch[0]->reverse ^= 1;
	}

	void disp()
	{
		NODE *p1, *p2;
		p1 = select(root, 1);
		p2 = select(root, N+2);
		splay(p1, NIL);
		splay(p2, root);
		print_s = false;
		scan(p2->ch[0]);
	}

	void scan(NODE *sour)
	{
		if(sour == NIL)
			return;
		push_down(sour);
		scan(sour->ch[0]);
		if(print_s)
			putchar(' ');
		printf("%d", sour->num);
		print_s = true;
		scan(sour->ch[1]);
	}
};

SPLAY_TREE spt;

char str[10];

int main()
{
	int m;
	while(scanf("%d%d", &N, &m), N >= 0 || m >= 0)
	{
		spt.init();
		int a, b, c;
		for(int i = 0; i < m; ++i)
		{
			scanf("%s", str);
			switch(str[0])
			{
			case 'C':	scanf("%d%d%d", &a, &b, &c);
						spt.CUT(a, b, c);
						break;
			case 'F':	scanf("%d%d", &a, &b);
						spt.FLIP(a, b);
						break;
			}
		}
		spt.disp();
		putchar('\n');
	}
	return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值