BZOJ-2733 永无乡

Treap+启发式合并。依旧没什么需要用到脑子的。

#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cctype>
#include <cstring>
#define rep(i, l, r) for(int i=l; i<=r; i++)
#define clr(x, c) memset(x, c, sizeof(x))
#define maxn 100009
using namespace std;
inline int read()
{
	int x=0; char ch=getchar();
	while (!isdigit(ch)) ch=getchar();
	while (isdigit(ch)) x=x*10+ch-'0', ch=getchar();
	return x;
}
int n=read(), m=read();
char q[5];


int h[maxn], l[maxn], r[maxn], s[maxn], k[maxn], pr[maxn];
inline void Init(){srand(2); rep(i, 1, n) s[i]=1, pr[i]=rand();}
inline void update(int x){s[x]=s[l[x]]+s[r[x]]+1;}
inline void Left(int v)
{
	int u=r[v];
	l[h[v]]==v ? l[h[v]]=u : r[h[v]]=u; h[u]=h[v];
	r[v]=l[u], h[r[v]]=v; 
	l[u]=v; h[v]=u; 
	update(v), update(u);
}
inline void Right(int v)
{
	int u=l[v];
	l[h[v]]==v ? l[h[v]]=u : r[h[v]]=u; h[u]=h[v];
	l[v]=r[u], h[l[v]]=v;
	r[u]=v, h[v]=u;
	update(v), update(u);
}
void Insert(int v, int u)
{
	if (k[v] < k[u])
	{
		if (!l[u]) {l[u]=v, h[v]=u; update(u); return;}
		Insert(v, l[u]); update(u);
		if (pr[l[u]] > pr[u]) Right(u);
	}
	else 
	{
		if (!r[u]) {r[u]=v, h[v]=u, update(u); return;}
		Insert(v, r[u]); update(u);
		if (pr[r[u]] > pr[u]) Left(u);
	}
}
int Top(int v){return h[v]==0 ? v : Top(h[v]);}
void Join(int v, int u)
{
	if (v==u) return;
	if (s[v]>s[u]) swap(v, u);
	int a=l[v], b=r[v];
	h[l[v]]=h[r[v]]=0, l[v]=r[v]=0, s[v]=1; 
	Insert(v, u); 
	if (a) Join(a, u); if (b) Join(b, u);
}
int Rank(int v, int k)
{
	if (s[v]<k) return -1; 
	while (s[l[v]]!=k-1) if (s[l[v]]>k-1) v=l[v]; else k-=s[l[v]]+1, v=r[v];
	return v;
}



int main()
{
	Init(); rep(i, 1, n) k[i]=read();
	rep(i, 1, m) Join(Top(read()), Top(read()));
	int o=read();
	rep(i, 1, o)
	{
		int x, y; scanf("%s%d%d", q, &x, &y);
		if (q[0]=='Q') printf("%d\n", Rank(Top(x), y)); else Join(Top(x), Top(y));
	}
	return 0;
}

  

posted @ 2015-04-21 20:14  NanoApe  阅读(201)  评论(0编辑  收藏  举报
AmazingCounters.com