题意:
给一个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;
}