zoukankan      html  css  js  c++  java
  • [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;
        
    }
  • 相关阅读:
    五、生产者消费者模型_ThreadLocal
    四、多线程基础-线程池的创建和使用
    spring根据beanName获取bean
    spring容器的功能扩展
    机甲大师S1机器人编程学习,Windows 10 安装Scratch和简单实例学习
    如何建设高可用系统
    详解Condition的await和signal等待/通知机制
    从源码角度彻底理解ReentrantLock(重入锁)
    MySQL 分库分表及其平滑扩容方案
    机甲大师S1机器人编程学习
  • 原文地址:https://www.cnblogs.com/evenbao/p/9365094.html
Copyright © 2011-2022 走看看