【NOIP2017】列队(Splay)

【NOIP2017】列队(Splay)

题面

洛谷

题解

其实好简单啊。。。
对于每一行维护一棵(Splay)
对于最后一列维护一棵(Splay)
(Splay)上一个节点表示一段区间
每次出去一个人就是把当前的(Splay)的一个节点拆分成(3)

然后就很简单了。。
细节比较多。。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 2000000
#define ls (t[x].ch[0])
#define rs (t[x].ch[1])
inline int read()
{
    RG int x=0,t=1;RG char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}
struct Node
{
	int ch[2],ff;
	ll size;
	ll l,r;
}t[MAX];
int tot;
int n,m,Q;
struct SplayTree
{
	int root;
	int Node(ll l,ll r){++tot;t[tot].l=l;t[tot].r=r;t[tot].size=r-l;return tot;}
	void pushup(int x){t[x].size=t[ls].size+t[rs].size+t[x].r-t[x].l;}
	void rotate(int x)
	{
		int y=t[x].ff,z=t[y].ff;
		int k=t[y].ch[1]==x;
		if(z)t[z].ch[t[z].ch[1]==y]=x;t[x].ff=z;
		t[y].ch[k]=t[x].ch[k^1];if(t[x].ch[k^1])t[t[x].ch[k^1]].ff=y;
		t[x].ch[k^1]=y;t[y].ff=x;
		pushup(y);pushup(x);
	}
	void Splay(int x)
	{
		for(int y=t[x].ff;y;rotate(x),y=t[x].ff)
			if(t[y].ff)(rand()&1)?rotate(x):rotate(y);
		root=x;
	}
	int Split(int x,ll K)
	{
		K+=t[x].l;
		int y=Node(K,t[x].r);t[x].r=K;
		if(!rs)t[y].ff=x,rs=y;
		else
		{
			int u=rs;
			while(t[u].ch[0])u=t[u].ch[0];
			t[y].ff=u;t[u].ch[0]=y;
		}
		Splay(y);return y;
	}
	ll DelKth(ll K)
	{
		int x=root;
		while(2333)
		{
			if(K<=t[ls].size)x=ls;
			else
			{
				K-=t[ls].size;
				if(K<=t[x].r-t[x].l)
				{
					if(K<t[x].r-t[x].l)Split(x,K);
					if(K>1)x=Split(x,K-1);
					break;
				}
				else K-=t[x].r-t[x].l,x=rs;
			}
		}
		Splay(x);t[ls].ff=t[rs].ff=0;
		if(!ls)root=rs;
		else
		{
			int y=ls;
			while(t[y].ch[1])y=t[y].ch[1];
			Splay(y);
			root=t[t[y].ch[1]=t[x].ch[1]].ff=y;
			pushup(y);
		}
		return t[x].l;
	}
	void Insert(ll k)
	{
		int y=Node(k,k+1);
		if(!root)root=y;
		else
		{
			int x=root;
			while(rs)x=rs;
			Splay(x);
			t[rs=y].ff=x;pushup(x);
		}
	}
}Splay[MAX];
int main()
{
	n=read();m=read();Q=read();
	for(int i=1;i<=n;++i)Splay[i].root=Splay[i].Node(1ll*i*m-m+1,1ll*i*m);
	for(int i=1;i<=n;++i)Splay[0].Insert(1ll*i*m);
	while(Q--)
	{
		int x=read(),y=read();ll ans;
		Splay[x].Insert(Splay[0].DelKth(x));
		printf("%lld
",ans=Splay[x].DelKth(y));
		Splay[0].Insert(ans);
	}
	return 0;
}

原文地址:https://www.cnblogs.com/cjyyb/p/8684116.html