hdoj 3436 queue-jumpers

一开始以为是一道搜索树的模板题,但是一看数据量10^8不能直接暴力搞了,之后就写了一篇巨长的代码,想了一下把top出的节点建树可以解决, 一开始想复杂了,导致我写了splay,SBT,hash,敲完代码手指头都有点抽了(o(╯□╰)o),后来看别人的题解发现都是离散化+离线解决的,而且只用splay就可以了,但是已经敲了这么长的代码,不忍心放弃,只好硬着头皮在线搞,还好都解决了,最后在求rank的时候遇到了一点障碍,如果有Rank i , i <= size, size为top出的不同数字个数,的时候可以直接在splay中找到排名为i的节点并把splay到树根,输出其中的记录的数字即可,然而i > size时,并不是很好搞,因为人的编号为1, 2, ..., n ,所以当没有top的时候直接输出i即可,如果有top的时候,就要判断一下大于等于i的数字有多少被top到前面去了,用i减去这些数的个数,然后还要判断一下top的数字中大于等于现在的i小于上一个i  的数字个数,然后再减去,以此循环直到数字个数为0,仅一次rank操作的最坏的复杂度是O(n*logn),后来在sbt里谢了个回溯fun函数可以解决这个问题,最后还不错1A了

#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(100010);
const int MOD(1313131);

template<typename T>
struct SBT
{
	struct NODE
	{
		T key;
		int size;
		NODE *left, *right;
	};
	
	NODE pool[MAXN];
	NODE *root, *NIL, *rear;
	T tkey;

	void init()
	{
		NIL = pool;
		NIL->left = NIL->right = NIL;
		NIL->size = 0;
		rear = pool+1;
		root = NIL;
	}

	void newnode(NODE *&sour, const T &value)
	{
		rear->key = value;
		rear->size = 1;
		rear->left = rear->right = NIL;
		sour = rear++;
	}

	void left_rotate(NODE *&sour)
	{
		NODE *temp = sour->right;
		sour->right = temp->left;
		temp->left = sour;
		temp->size = sour->size;
		sour->size = sour->left->size+sour->right->size+1;
		sour = temp;
	}

	void right_rotate(NODE *&sour)
	{
		NODE *temp = sour->left;
		sour->left = temp->right;
		temp->right = sour;
		temp->size = sour->size;
		sour->size = sour->left->size+sour->right->size+1;
		sour = temp;
	}

	void maintain(NODE *&sour, bool flag)
	{
		if(flag == false)
		{
			if(sour->left->left->size > sour->right->size)
				right_rotate(sour);
			else
				if(sour->left->right->size > sour->right->size)
				{
					left_rotate(sour->left);
					right_rotate(sour);
				}
				else
					return;
		}
		else
		{
			if(sour->right->right->size > sour->left->size)
				left_rotate(sour);
			else
				if(sour->right->left->size > sour->left->size)
				{
					right_rotate(sour->right);
					left_rotate(sour);
				}
				else
					return;
		}
		maintain(sour->right, true);
		maintain(sour->left, false);
		maintain(sour, true);
		maintain(sour, false);
	}

	void insert(const T &value)
	{
		tkey = value;
		insert_(root);
	}

	void insert_(NODE *&sour)
	{
		if(sour == NIL)
		{
			newnode(sour, tkey);
			return;
		}
		++sour->size;
		if(tkey < sour->key)
			insert_(sour->left);
		else
			insert_(sour->right);
		maintain(sour, tkey >= sour->key);
	}

	NODE *search(const T &value)
	{
		NODE *sour = root;
		while(root != NIL && sour->key != value)
		{
			if(value < sour->key)
				sour = sour->left;
			else
				sour = sour->right;
		}
		return sour;
	}

	int rank(const T &value)
	{
		NODE *sour = root;
		int ret = 1;
		while(sour != NIL)
		{
			if(value <= sour->key)
				sour = sour->left;
			else
			{
				ret += sour->left->size+1;
				sour = sour->right;
			}
		}
		return ret;
	}

	NODE *successor(const T& value)
	{
		tkey = value;
		return successor(root);
	}

	NODE *successor_(NODE *sour)
	{
		if(sour == NIL)
			return NIL;
		if(tkey < sour->key)
		{
			NODE *temp = successor_(sour->left);
			if(temp == NIL)
				return sour;
			else
				return temp;
		}
		else
		{
			return successor_(sour->right);
		}
	}

	int tv;
	int ret;

	int fun(int value)
	{
		tv = value;
		fun_(root);
		return tv;
	}

	void fun_(NODE *sour)
	{
		if(sour == NIL)
			return;
		if(tv <= sour->key.num)
		{
			tv -= sour->right->size+1;
			fun_(sour->left);
		}
		else
		{
			fun_(sour->right);
			if(tv <= sour->key.num)
			{
				tv -= 1;
				fun_(sour->left);
			}
		}
	}
	
};

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

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

	inline void push_up(NODE *sour)
	{
		sour->size = sour->ch[0]->size+sour->ch[1]->size+1;
	}
	
	void init()
	{
		NIL = pool;
		NIL->fa = NIL->ch[0] = NIL->ch[1] = NIL;
		NIL->size = 0;
		rear = pool+1;
		newnode(root, NIL, -1);
		newnode(root->ch[1], root, -1);
		ll = root;
		rl = root->ch[1];
		push_up(rl);
		push_up(ll);
	}

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

	void rotate(NODE *sour, int flag)
	{
		NODE *f = sour->fa;
		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)
	{
		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 *extreme(NODE *sour, int flag)
	{
		while(sour->ch[flag] != NIL)
			sour = sour->ch[flag];
		return sour;
	}

	NODE *insert(int tn)
	{
		splay(ll, NIL);
		splay(rl, root);
		NODE *temp = extreme(rl, 0);
		newnode(temp->ch[0], temp, tn);
		splay(temp->ch[0], NIL);
		return root;
	}

	void erase(NODE *sour)
	{
		splay(sour, NIL);
		NODE *p1, *p2;
		p1 = extreme(sour->ch[0], 1);
		p2 = extreme(sour->ch[1], 0);
		splay(p1, NIL);
		splay(p2, root);
		p2->ch[0] = NIL;
		push_up(p2);
		push_up(p1);
	}

	NODE *select(int r)
	{
		NODE *sour = root;
		while(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];
			}
		}
		splay(sour, NIL);
		return root;
	}
};

struct HASH
{
	struct NODE
	{
		int num;
		NODE *next;
	};

	NODE *head[MOD];
	NODE pool[MAXN];
	NODE *rear;
	void init()
	{
		memset(head, 0, sizeof(head));
		rear = pool;
	}

	inline int hash(int num)
	{
		return num%MOD;
	}
	void insert(int num)
	{
		int h = hash(num);
		for(NODE *i = head[h]; i; i = i->next)
			if(i->num == num)
				return;
		rear->num = num;
		rear->next = head[h];
		head[h] = rear++;
	}

	bool search(int num)
	{
		int h = hash(num);
		for(NODE *i = head[h]; i; i = i->next)
			if(i->num == num)
				return true;
		return false;
	}
};

struct ELE
{
	int num;
	SPLAY_TREE::NODE *ptr;
	ELE()
	{}
	ELE(int tn, SPLAY_TREE::NODE *tp): num(tn), ptr(tp)
	{}
	friend bool operator < (const ELE &op1, const ELE &op2)
	{
		return op1.num < op2.num;
	}
	friend bool operator >= (const ELE &op1, const ELE &op2)
	{
		return op1.num >= op2.num;
	}
	friend bool operator <= (const ELE &op1, const ELE &op2)
	{
		return op1.num <= op2.num;
	}
	friend bool operator == (const ELE &op1, const ELE &op2)
	{
		return op1.num == op2.num;
	}
	friend bool operator != (const ELE &op1, const ELE &op2)
	{
		return op1.num != op2.num;
	}
};

SBT<ELE> sbt;
SPLAY_TREE spt;
HASH hash_table;

int main()
{
	int T;
	scanf("%d", &T);
	char str[10];
	int op;
	int n_case(0);
	while(T--)
	{
		sbt.init();
		spt.init();
		hash_table.init();
		int N, Q;
		printf("Case %d:\n", ++n_case);
		scanf("%d%d", &N, &Q);
		for(int i = 0; i < Q; ++i)
		{
			scanf("%s%d", str, &op);
			if(str[0] == 'T')
			{
				if(hash_table.search(op))
				{
					SBT<ELE>::NODE *p = sbt.search(ELE(op, NULL));
					spt.erase(p->key.ptr);
					p->key.ptr = spt.insert(op);
				}
				else
				{
					hash_table.insert(op);
					SPLAY_TREE::NODE *p = spt.insert(op);
					sbt.insert(ELE(op, p));
				}
			}
			else
				if(str[0] == 'Q')
				{
					if(hash_table.search(op))
					{
						SBT<ELE>::NODE *p = sbt.search(ELE(op, NULL));
						spt.splay(p->key.ptr, spt.NIL);
						printf("%d\n", spt.root->ch[0]->size);
					}
					else
					{
						int temp = sbt.rank(ELE(op, NULL));
						printf("%d\n", op+(sbt.root->size-(temp-1)));
					}
				}
				else
				{
					if(op <= sbt.root->size)
					{
						SPLAY_TREE::NODE *p = spt.select(op+1);
						printf("%d\n", p->num);
					}
					else
					{
//						int temp = sbt.rank(ELE(op, NULL));
//						int ret = op-(sbt.root->size-(temp-1));
//						while(hash_table.search(ret))
//							--ret;
						printf("%d\n", sbt.fun(op));
					}
				}
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值