【Treap】[Scoi2014] bzoj3595 方伯伯的Oj

题目点这里 


cena卡STL。。所以双treap见:http://blog.csdn.net/qq_21841245/article/details/44977711。。


这道题见证了什么叫做一时手贱千古恨 :) 强制在线的离散化 想写对拍都不容易orz用了各种乱七八糟的查错方法终于知道错哪了!!!

orz交了bzoj拿了rank3 指针写比鲲哥快哈哈哈哈 当心理安慰吧 = =。。纪念我被这道题挫伤的小心脏啊。。。


这题维护序列。。用splay挺好的 treap也行直接把它的“排名”当做排序关键字就行了(提到前面的就是负的 其实这是鲲哥的思路 orz)

然后开个map保存每个编号对应的排序关键字 每次查找就行了 对于那些写双splay的 只能orz

因为空间开不下 所以把m[x] == 0的情况当做它的编号就是自己本身 所以千万不能用到0作为排序关键字!!!!!!!!!!千万!!!!!!


#include <cstdio>
#include <iostream>
#include <map>
#include <cstdlib>

using namespace std;

int read()
{
	int n = 0, sign = 1; char c = getchar();
	while(c > '9' || c < '0') {if(c == '-') sign = -1; c = getchar();}
	while(c >= '0' && c <= '9') {n = n*10 + c-'0'; c = getchar(); }
	return sign * n;
}

const int inf = 0x3f3f3f3f;

map <int, int> m;

int cnt = 1;
struct treap{
	struct node{
		node *lc, *rc, *f;
		int s, id, r, L, R;
	}t[300055], *null, *root;
	
	inline void init()
	{
		null = &t[0]; null -> lc = null -> rc = null -> f = null;
		null -> s = 0; null -> id = null -> L = null -> R = null -> r = -inf;
		root = null;
	}
	
	inline node *NewNode(int index, int L, int R)
	{
		t[cnt].lc = t[cnt].rc = t[cnt].f = null; t[cnt].r = rand();
		t[cnt].id = index; t[cnt].L = L; t[cnt].R = R; t[cnt].s = R - L + 1;
		return &t[cnt++];
	}
	
	inline void pushup(node *&p){ p->s = p->lc->s + p->rc->s + (p->R-p->L+1);}
	
	inline void maintain(node *&p)
	{
		if(p->lc->r > p->r)
		{
			node *temp = p -> lc;
			p -> lc = temp -> rc;
			temp -> rc = p;
			pushup(p); p = temp;
		} 
		else if(p->rc->r > p->r)
		{
			node *temp = p -> rc;
			p -> rc = temp -> lc;
			temp -> lc = p;
			pushup(p); p = temp;
		}
		pushup(p);
	}
	
	void insert(node *&p, int L, int R, int index)
	{
		if(p == null)
		{
			p = NewNode(index, L, R);
			return;
		}
		if(R < p -> L) insert(p -> lc, L, R, index);
		else insert(p -> rc, L, R, index);
		maintain(p);
	}
	
	void merge(node *&ne, node *p, node *q)
	{
		if(p == null || q == null)
		{
			ne = p == null ? q : p;
			return;
		}
		if(p->r > q->r) { ne = p; merge(ne->rc, p->rc, q); }
		else{ ne = q; merge(ne->lc, p, q->lc); }
		pushup(ne);
	}
	
	void del(node *&p, int pos)
	{
		if(p == null) return;
		if(p->L <= pos && pos <= p->R)
		{
			if(p->L == p->R) merge(p, p->lc, p->rc); // 经证实这句是错的。不过反正窝退役了不管了2333
			else if(p->L == pos) { ++ p -> L; ++ p -> id; pushup(p); }
			else if(p->R == pos) { -- p -> R; pushup(p); }
			else
			{
				insert(p -> rc, pos + 1, p -> R, pos + 1);
				p -> R = pos - 1; pushup(p);
			}
			return;
		}
		if(p->L > pos) del(p -> lc, pos);
		else del(p -> rc, pos); maintain(p);
	}
	
	int getrank(node *p, int pos)
	{
		if(p == null) return 0;
		if(p->L <= pos && pos <= p->R) return (pos - p->L + 1) + p->lc->s;
		if(p->L > pos) return getrank(p->lc, pos);
		else return getrank(p->rc, pos) + p->lc->s + (p->R - p->L + 1);
	}
	
	int getindex(node *p, int k)
	{
		if(p == null) return 0;
		int lsize = p->lc->s; 
		if(k <= lsize) return getindex(p->lc, k);
		if(lsize < k && lsize + (p->R - p->L + 1) >= k)
		{
			if(p->L == p->R) return p->id;
			else return k-lsize-1 + p->L;
		}
		else return getindex(p->rc, k - lsize - (p->R - p->L + 1));
	}
}t;

int N, M;

int main()
{
	srand(20150233); t.init();
	N = read(); t.insert(t.root, 1, N, 1);
	int mmin = 0, mmax = N, a = 0; 
	for(M = read(); M--; )
	{
		int sign = read(), x = read(); x -= a;
		if(sign == 1)
		{
			int y = read(); y -= a;
			int pos = m[x]; if(!pos) pos = x;
			printf("%d\n", a = t.getrank(t.root, pos));
			t.del(t.root, pos); 
			t.insert(t.root, pos, pos, y); 
			m[x] = 0; m[y] = pos;
		}
		else if(sign == 2)
		{
			int pos = m[x]; if(!pos) pos = x;
			printf("%d\n", a = t.getrank(t.root, pos));
			t.del(t.root, pos); m[x] = pos = --mmin;
			t.insert(t.root, pos, pos, x);
		}
		else if(sign == 3)
		{
			int pos = m[x]; if(!pos) pos = x;
			printf("%d\n", a = t.getrank(t.root, pos));
			t.del(t.root, pos); m[x] = pos = ++mmax;
			t.insert(t.root, pos, pos, x);
		}
		else printf("%d\n", a = t.getindex(t.root, x));
	}
	
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值