[NOIP 2017] 列队

[题目链接]

         http://uoj.ac/problem/334

[算法]

         仔细观察依次下达的两条指令,我们发现,其实需要做的就是 :

         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;
    
}
原文地址:https://www.cnblogs.com/evenbao/p/9365094.html