NOIP2017提高组D2T3[列队]

题意:

给一个n行m列的方阵,第i行第j列的人编号为(i-1)*m+j,每次会有一个人出列,所有人先向m=1一列补齐,再向n=1一行补齐,然后出列的人补在n行m列,问每次出列的人的编号。

题解:

平衡树动态开节点,每行前m-1个人记录一个平衡树,最后一列单独记一个平衡树,最好用Splay或者无旋Treap。

代码:

#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

struct Node
{
	int ch[2],fa;
	long long l,r,size;
	Node(){ch[0] = ch[1] = fa = 0,l = r = size = 0;}
	Node(long long l_,long long r_)
	{
		l = l_;
		r = r_;
		size = r - l + 1;
		ch[0] = ch[1] = fa = 0;
	}
	bool check(){return l <= r;}
}node[3000005];

long long n,m,q,id,pos;
int root[300005];

void Update(int u)
{
	node[u].size = node[u].r - node[u].l + 1;
	if (node[u].ch[0])
		node[u].size += node[node[u].ch[0]].size;
	if (node[u].ch[1])
		node[u].size += node[node[u].ch[1]].size;
}

void Link(int fa,int ch,bool dir)
{
	node[fa].ch[dir] = ch;
	if (ch)
		node[ch].fa = fa;
	Update(fa);
}

bool is_root(int u)
{
	return !node[u].fa;
}

void Rotate(int u,bool dir)
{
	int ch = node[u].ch[dir],fa = node[u].fa;
	bool ok = is_root(u);
	Link(u,node[ch].ch[!dir],dir);
	Link(ch,u,!dir);
	node[ch].fa = fa;
	if (!ok)
		node[fa].ch[node[fa].ch[1] == u] = ch;
}

int Insert(int u,long long l,long long r)
{
	if (!u)
	{
		node[u = ++id] = Node(l,r);
		return u;
	}
	node[u].ch[1] = Insert(node[u].ch[1],l,r);
	node[node[u].ch[1]].fa = u;
	return u;
}

int Splay(int u)
{
	while (!is_root(u))
	{
		int fa = node[u].fa;
		bool dir1 = (node[fa].ch[1] == u);
		if (is_root(fa))
		{
			Rotate(fa,dir1);
			break;
		}
		int ffa = node[fa].fa;
		bool dir2 = (node[ffa].ch[1] == fa);
		if (dir1 ^ dir2)
		{
			Rotate(fa,dir1);
			Rotate(ffa,dir2);
		}
		else
		{
			Rotate(ffa,dir2);
			Rotate(fa,dir1);
		}
	}
	return u;
}

int GetMAX(int u)
{
	if (node[u].ch[1])
		return GetMAX(node[u].ch[1]);
	return u;
}

int get_size(int u)
{
	return u ? node[u].size : 0;
}

int Merge(int a,int b)
{
	if (!a)
		return b;
	if (!b)
		return a;
	int ret = GetMAX(a);
	ret = Splay(ret);
	Link(ret,b,1);
	return ret;
}

int Getans(int u,long long x)
{
	if (get_size(node[u].ch[0]) >= x)
		return Getans(node[u].ch[0],x);
	x -= get_size(node[u].ch[0]);
	if (node[u].r - node[u].l + 1 >= x)
	{
		pos = x - 1;
		return u;
	}
	x -= node[u].r - node[u].l + 1;
	return Getans(node[u].ch[1],x);
}

int main()
{
	freopen("phalanx.in","r",stdin);
	freopen("phalanx.out","w",stdout);
	ios::sync_with_stdio(false);
	cin >> n >> m >> q;
	for (int i = 1;i <= n;i++)
	{
		root[i] = Insert(root[i],(i - 1) * m + 1,i * m - 1);
		root[n + 1] = Insert(root[n + 1],i * m,i * m);
		root[n + 1] = Splay(id);
	}
	root[n + 1] = Splay(2);
	for (int x,y,i = 1;i <= q;i++)
	{
		cin >> x >> y;
		if (y == m)
		{
			pos = 0;
			int ret = Getans(root[n + 1],x);
			cout << node[ret].l << endl;
			root[n + 1] = Splay(ret);
			if (node[root[n + 1]].ch[0])
				node[node[root[n + 1]].ch[0]].fa = 0;
			if (node[root[n + 1]].ch[1])
				node[node[root[n + 1]].ch[1]].fa = 0;
			root[n + 1] = Merge(node[root[n + 1]].ch[0],node[root[n + 1]].ch[1]);
			root[n + 1] = Insert(root[n + 1],node[ret].l,node[ret].l);
			root[n + 1] = Splay(id);
		}
		else
		{
			pos = 0;
			int ret2 = Getans(root[n + 1],x),ret = Getans(root[x],y);
			cout << node[ret].l + pos << endl;
			root[x] = Splay(ret);
			root[n + 1] = Splay(ret2);
			int l = ++id,r = ++id;
			node[l] = Node(node[ret].l,node[ret].l + pos - 1);
			node[r] = Node(node[ret].l + pos + 1,node[ret].r);
			if (node[l].check() && node[r].check())
			{
				Link(l,node[root[x]].ch[0],0);
				Link(r,node[root[x]].ch[1],1);
				root[x] = Merge(l,r);
			}
			else if (node[r].check())
			{
				Link(r,node[root[x]].ch[0],0);
				Link(r,node[root[x]].ch[1],1);
				root[x] = r;
			}
			else if (node[l].check())
			{
				Link(l,node[root[x]].ch[0],0);
				Link(l,node[root[x]].ch[1],1);
				root[x] = l;
			}
			else
			{
				if (node[root[x]].ch[0])
					node[node[root[x]].ch[0]].fa = 0;
				if (node[root[x]].ch[1])
					node[node[root[x]].ch[1]].fa = 0;
				root[x] = Merge(node[root[x]].ch[0],node[root[x]].ch[1]);
			}
			root[x] = Insert(root[x],node[ret2].l,node[ret2].l);
			root[x] = Splay(id);
			if (node[root[n + 1]].ch[0])
				node[node[root[n + 1]].ch[0]].fa = 0;
			if (node[root[n + 1]].ch[1])
				node[node[root[n + 1]].ch[1]].fa = 0;
			root[n + 1] = Merge(node[root[n + 1]].ch[0],node[root[n + 1]].ch[1]);
			root[n + 1] = Insert(root[n + 1],node[ret].l + pos,node[ret].l + pos);
			root[n + 1] = Splay(id);
		}
	}
	return 0;
}




你可能感兴趣的:(NOIP)