【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\n",ans=Splay[x].DelKth(y));
Splay[0].Insert(ans);
}
return 0;
}
原文地址:https://www.cnblogs.com/cjyyb/p/8684116.html
时间: 2024-10-09 01:38:46