SPLAY树

开始以为splay就是普通的BST,后来看了hh神和撞神的文章才知道splay可以当做线段树用,而且还可以完成区间插入和区间删除等这些线段树完成不了的工作,及其的灵活.

Daniel Sleator & Robert Tarjan & ACMer & OIer ORZ

poj 3667

#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>

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(50010);
int n;

template<typename T1, typename T2>
struct SPLAY_TREE
{
	struct NODE
	{
		T1 key;
		T2 cover;
		T2 color;
		int size;
		T2 lsum, rsum, msum;
		NODE *fa;
		NODE *ch[2];
	};

	NODE *root, *NIL, *rear;
	NODE pool[MAXN];

	void init()
	{
		NIL = pool;
		NIL->fa = NIL;
		NIL->ch[0] = NIL;
		NIL->ch[1] = NIL;
		NIL->key = -1;
		NIL->cover = -1;
		NIL->color = NIL->size = NIL->lsum = NIL->rsum = NIL->msum = 0;
		rear = pool+1;
		newnode(root, NIL, 0, 1);
		newnode(root->ch[1], root, n+1, 1);
		build_tree(1, n, root->ch[1]->ch[0], root->ch[1]);
		push_up(root->ch[1]);
		push_up(root);
	}

	void newnode(NODE *&sour, NODE *f, const T1 &value1, const T2 &value2)
	{
		rear->key = value1;
		rear->cover = -1;
		rear->color = value2;
		rear->ch[0] = rear->ch[1] = NIL;
		rear->fa = f;
		rear->size = 1;
		sour = rear++;
	}

	void push_up(NODE *sour)
	{
		sour->lsum = sour->ch[0]->lsum;
		sour->rsum = sour->ch[1]->rsum;
		if(sour->lsum == sour->ch[0]->size && sour->color != 1)
			sour->lsum += sour->ch[1]->lsum+1;
		if(sour->rsum == sour->ch[1]->size && sour->color != 1)
			sour->rsum += sour->ch[0]->rsum+1;
		sour->msum = max(sour->ch[0]->msum, sour->ch[1]->msum);
		if(sour->color != 1)
			sour->msum = max(sour->msum, sour->ch[0]->rsum+sour->ch[1]->lsum+1);
		sour->size = sour->ch[0]->size+sour->ch[1]->size+1;
	}

	void push_down(NODE *sour)
	{
		if(sour->cover != -1)
		{
			sour->ch[0]->cover = sour->ch[0]->color = sour->cover;
			sour->ch[1]->cover = sour->ch[1]->color = sour->cover;
			sour->ch[0]->lsum = sour->ch[0]->rsum = sour->ch[0]->msum = sour->cover? 0: sour->ch[0]->size;
			sour->ch[1]->lsum = sour->ch[1]->rsum = sour->ch[1]->msum = sour->cover? 0: sour->ch[1]->size;
			sour->cover = -1;
		}
	}

	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(int r, NODE *sour)
	{
		push_down(sour);
		while(sour != NIL && r != sour->ch[0]->size+1)
		{
			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;
	}

	NODE *find(int op, NODE *sour)
	{
		if(op > sour->msum)
			return NIL;
		push_down(sour);
		NODE *ret;
		while(sour != NIL)
		{
			if(op <= sour->ch[0]->msum)	
				sour = sour->ch[0];
			else
				if(sour->color != 1 && op <= sour->ch[0]->rsum+sour->ch[1]->lsum+1)
				{
					ret = select(sour->ch[0]->size-sour->ch[0]->rsum+1, sour);
					break;
				}
				else
					sour = sour->ch[1];
			push_down(sour);
		}
		return ret;
	}

	NODE *search(const T1 &value)
	{
		NODE *sour = root;
		push_down(sour);
		while(sour != NIL && value != sour->key)
		{
			sour = sour->ch[value > sour->key];
			push_down(sour);
		}
		return sour;
	}

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

	void updata(int ql, int qr, int op)
	{
		NODE *sour = select(ql, root);
		splay(sour, NIL);
		sour = select(qr+2, root);
		splay(sour, root);
		sour = root->ch[1]->ch[0];
		sour->color = sour->cover = op;
		sour->lsum = sour->rsum = sour->msum = op? 0: sour->size;
	}
	
	int query(int op)
	{
		NODE *sour = select(1, root);
		splay(sour, NIL);
		sour = select(n+2, root);
		splay(sour, root);
		sour = find(op, root->ch[1]->ch[0]);
		if(sour == NIL)
			return 0;
		else
			return sour->key;
	}
	void debug()
	{
		printf("/****************************************/\n");
		debug_(root, 0);
		printf("/****************************************/\n");
	}

	void debug_(NODE *sour, int vec)
	{
		if(sour == NIL)
			return;
		debug_(sour->ch[0], vec+1);
		for(int i = 0; i < vec; ++i)
			printf("          ");
		printf("(%d, %d, %d, %d)\n", sour->key, sour->lsum, sour->rsum, sour->msum);
		debug_(sour->ch[1], vec+1);
	}
};

SPLAY_TREE<int, int> spt;

int main()
{
	int m;
	int flag, op1, op2, ret;
//	freopen("d:\\out.txt", "w", stdout);
	while(~scanf("%d%d", &n, &m))
	{
		spt.init();
		for(int i = 0; i < m; ++i)
		{
			scanf("%d", &flag);
			if(flag == 1)
			{
				scanf("%d", &op1);
				ret = spt.query(op1);
				printf("%d\n", ret);
				if(ret != 0)
					spt.updata(ret, ret+op1-1, 1);
			}
			else
			{
				scanf("%d%d", &op1, &op2);
				spt.updata(op1, op1+op2-1, 0);
			}
		//	spt.debug();
		}
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值