[题目链接]
[算法]
仔细观察依次下达的两条指令,我们发现,其实需要做的就是 :
1. 将最后一列的第x个数弹出,插入到第x行的末尾
2. 将第x行的第y个数弹出,插入到最后一行最后一列
不妨建(n + 1)棵平衡树,维护n行和最后一列,但是这样的空间复杂度是O(NM)的,会导致内存超限
我们发现在初始情况下,所有节点的编号是连续的,不妨将这些编号连续的节点合并为1个节点,这样就能避免空间超限
[代码]
笔者代码中使用的平衡树为伸展树
#include<bits/stdc++.h> using namespace std; const int MAXN = 3 * 1e5 + 10; #define MAXP 2400010 typedef long long ll; ll i,n,m,q,x,y; ll tmp; ll tot; struct Node { ll fa; ll son[2]; ll l,r; ll size; } Tree[MAXP]; struct Splay { ll root; inline ll new_node(ll l,ll r) { tot++; Tree[tot].fa = Tree[tot].son[0] = Tree[tot].son[1] = 0; Tree[tot].l = l; Tree[tot].r = r; Tree[tot].size = r - l + 1; return tot; } inline void update(ll index) { Tree[index].size = Tree[index].r - Tree[index].l + 1; Tree[index].size += Tree[Tree[index].son[0]].size; Tree[index].size += Tree[Tree[index].son[1]].size; } inline bool get(ll x) { return Tree[Tree[x].fa].son[1] == x; } inline void rotate(ll x) { ll f = Tree[x].fa,g = Tree[f].fa; ll tmpx = get(x),tmpf = get(f); if (!f) return; Tree[f].son[tmpx] = Tree[x].son[tmpx ^ 1]; if (Tree[x].son[tmpx ^ 1]) Tree[Tree[x].son[tmpx ^ 1]].fa = f; Tree[x].son[tmpx ^ 1] = f; Tree[f].fa = x; Tree[x].fa = g; if (g) Tree[g].son[tmpf] = x; update(f); update(x); } inline void splay(ll x) { ll fa; for (fa = Tree[x].fa; (fa = Tree[x].fa); rotate(x)) rotate((get(fa) == get(x)) ? fa : x); root = x; } inline void init(ll l,ll r) { root = new_node(l,r); } inline ll split(ll x,ll k) { ll tmp,y; k += Tree[x].l; y = new_node(k,Tree[x].r); Tree[x].r = k - 1; if (Tree[x].son[1] == 0) { Tree[x].son[1] = y; Tree[y].fa = x; } else { tmp = Tree[x].son[1]; while (Tree[tmp].son[0]) tmp = Tree[tmp].son[0]; Tree[tmp].son[0] = y; Tree[y].fa = tmp; while (tmp != x) { update(tmp); tmp = Tree[tmp].fa; } } splay(y); return y; } inline void join(ll x,ll y) { ll now = x; while (Tree[now].son[1]) now = Tree[now].son[1]; splay(now); Tree[now].son[1] = y; Tree[y].fa = now; } inline ll pop(ll k) { ll now = root; while (true) { if (k <= Tree[Tree[now].son[0]].size) now = Tree[now].son[0]; else { k -= Tree[Tree[now].son[0]].size; if (k <= Tree[now].r - Tree[now].l + 1) { if (k != Tree[now].r - Tree[now].l + 1) split(now,k); if (k != 1) now = split(now,k - 1); break; } else { k -= Tree[now].r - Tree[now].l + 1; now = Tree[now].son[1]; } } } splay(now); if (!Tree[now].son[0] && !Tree[now].son[1]) { root = 0; return Tree[now].l; } if (!Tree[now].son[0]) { root = Tree[now].son[1]; Tree[root].fa = 0; return Tree[now].l; } if (!Tree[now].son[1]) { root = Tree[now].son[0]; Tree[root].fa = 0; return Tree[now].l; } join(Tree[now].son[0],Tree[now].son[1]); return Tree[now].l; } inline void push_back(ll x) { ll now = root; ll y = new_node(x,x); if (!root) root = y; else { while (Tree[now].son[1]) now = Tree[now].son[1]; splay(now); Tree[now].son[1] = y; Tree[y].fa = now; update(now); } } } T[MAXN]; int main() { scanf("%d%d%d",&n,&m,&q); for (i = 1; i <= n; i++) T[i].init((i - 1) * m + 1,i * m - 1); T[n + 1].init(m,m); for (i = 2; i <= n; i++) T[n + 1].push_back(i * m); while (q--) { scanf("%d%d",&x,&y); tmp = T[n + 1].pop(x); T[x].push_back(tmp); tmp = T[x].pop(y); printf("%lld ",tmp); T[n + 1].push_back(tmp); } return 0; }