zoukankan      html  css  js  c++  java
  • 题解 P3960 【列队】

    题目链接:Link

    Problem

    Solution

    考虑到每个点都是先横向移动,然后再纵向移动,所以我们可以考虑每行维护一个splay,最后一列再维护一个splay。
    但是考虑到n和m的规模都是(3*10^5)级别的,普通的splay肯定会爆空间,所以我们使用动态开点的splay,对于每个节点记录一个L和一个R,如果需要splay的元素在这个区间当中,就把当前节点拆成3个,将左侧部分和右侧部分分别插入到左子树的最右边和右子树的最左边。
    然后接下来就是一些细节问题了:

    • 别忘开long long
    • splay在拆点时要特别注意判断条件
    • 小心只有一列或要出列的人在最后一列的情况

    Code

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    struct Node
    {
        int s; LL L,R;
        Node* ch[2];
        inline void PU() { s=ch[0]->s+R-L+1+ch[1]->s; }
        inline int cmp(int k)
        {
            int d=k-ch[0]->s;
            return d>=1&&d<=R-L+1?-1:d>1;
        }
    };
    Node *null=new Node();
    inline Node* NN(LL L,LL R)
    {
        Node *o=new Node();
        o->L=L; o->R=R; o->s=R-L+1;
        o->ch[0]=o->ch[1]=null;
        return o;
    }
    inline void rotate(Node* &o,int d)
    {
        Node* p=o->ch[d^1];
        o->ch[d^1]=p->ch[d]; p->ch[d]=o;
        o->PU();
        p->PU();
        o=p;
    }
    void Add(Node* &o,Node *v,int d)
    {
        if(o==null) { o=v; return; }
        Add(o->ch[d],v,d);
        o->PU();
    }
    inline void cut(Node* &o,int k)
    {
        LL L=o->L,R=o->R,s=R-L+1;
        o->L=o->R=L+k-1;
        if(k-1>=1) Add(o->ch[0],NN(L,L+k-2),1);
        if(k+1<=s) Add(o->ch[1],NN(L+k,R),0);
        o->PU();
    }
    void splay(Node* &o,int k)
    {
        int d=o->cmp(k);
        if(d==-1&&o->R-o->L+1>1) cut(o,k);
        if(d==1) k-=o->ch[0]->s+1;
        if(d!=-1)
        {
            Node *p=o->ch[d];
            int d2=p->cmp(k);
            if(d2==-1&&p->R-p->L+1>1) cut(p,k);
            if(d2==1) k-=p->ch[0]->s+1;
            if(d2!=-1)
            {
                splay(p->ch[d2],k);
                if(d==d2) rotate(o,d^1);
                else rotate(o->ch[d],d);
            }
            rotate(o,d^1);
        }
    }
    inline Node* merge(Node *left,Node *right)
    {
        splay(left,left->s);
        left->ch[1]=right;
        left->PU();
        return left;
    }
    inline void split(Node *o,int k,Node* &left,Node* &right)
    {
        splay(o,k);
        left=o;
        right=o->ch[1];
        o->ch[1]=null;
        left->PU();
    }
    inline void dfsx(Node* o)
    {
        if(o==null) return;
        dfsx(o->ch[0]);
        for(int i=o->L;i<=o->R;i++) printf("%d ",i);
        dfsx(o->ch[1]);
    }
    #define print(x) do { printf("%s: ",#x); dfsx(x); puts(""); } while(0)
    //以上为splay模板
    const int maxn=3e5+5;
    LL n,m,q;
    Node *r[maxn],*lst;
    int main()
    {
    #ifdef local
    //	freopen("testdata.in","r",stdin);
    //	freopen("pro.out","w",stdout);
        freopen("pro.in","r",stdin);
    #endif
        null->ch[0]=null->ch[1]=null; null->s=0;
        dfsx(null);
        scanf("%lld%lld%lld",&n,&m,&q);
        for(int i=1;i<=n;i++)
        {
            if(m>=2) r[i]=merge(NN(-1,-1),NN((i-1)*m+1,(i-1)*m+1+m-2));
            else r[i]=NN(-1,-1);
        }
        lst=NN(-1,-1);
        for(int i=1;i<=n;i++) lst=merge(lst,NN(i*m,i*m));
        for(int i=1;i<=q;i++)
        {
            int x,y; scanf("%d%d",&x,&y);
            if(y<m)
            {
                Node *a,*b,*c,*d,*e,*f;
                split(r[x],y,a,b);
                split(b,1,b,c);
                split(lst,x,d,e);
                split(e,1,e,f);
                printf("%lld
    ",b->L);
                r[x]=merge(merge(a,c),e);
                lst=merge(merge(d,f),b);
            }
            else
            {
                Node *a,*b,*c;
                split(lst,x,a,b);
                split(b,1,b,c);
                printf("%lld
    ",b->L);
                lst=merge(merge(a,c),b);
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    Swift学习笔记(7)--控制流
    安装APK时报 Installation failed with message Failed to finalize session : INSTALL_FAILED_USER_RESTRICTED: Invalid apk.
    Android Notification 的四种使用方式
    Socket.io
    socket
    socket.io 中文手册 socket.io 中文文档
    Android中的CardView使用
    TabLayout实现底部导航栏(2)
    使用PagerSlidingTabStrip实现顶部导航栏
    TabLayout实现顶部导航栏(1)
  • 原文地址:https://www.cnblogs.com/happyZYM/p/11379575.html
Copyright © 2011-2022 走看看