zoukankan      html  css  js  c++  java
  • 【NOIP2017D2T3】列队

    Description
      Sylvia 是一个热爱学习的女孩子。
      前段时间,Sylvia 参加了学校的军训。众所周知,军训的时候需要站方阵。Sylvia所在的方阵中有n × m名学生,方阵的行数为 n,列数为 m。
      为了便于管理,教官在训练开始时,按照从前到后,从左到右的顺序给方阵中的学生从 1 到 n × m 编上了号码(参见后面的样例)。即:初始时,第 i 行第 j 列的学生的编号是(i - 1) × m + j。
      然而在练习方阵的时候,经常会有学生因为各种各样的事情需要离队。在一天中,一共发生了 q 件这样的离队事件。每一次离队事件可以用数对(x, y) (1≤x≤n,1≤y≤m)描述,表示第 x 行第 y 列的学生离队。
      在有学生离队后,队伍中出现了一个空位。为了队伍的整齐,教官会依次下达这样的两条指令:
      1. 向左看齐。这时第一列保持不动,所有学生向左填补空缺。不难发现在这条指令之后,空位在第 x 行第 m 列。
      2. 向前看齐。这时第一行保持不动,所有学生向前填补空缺。不难发现在这条指令之后,空位在第 n 行第 m 列。
      教官规定不能有两个或更多学生同时离队。即在前一个离队的学生归队之后,下一个学生才能离队。因此在每一个离队的学生要归队时,队伍中有且仅有第 n 行第 m 列一个空位,这时这个学生会自然地填补到这个位置。
      因为站方阵真的很无聊,所以 Sylvia 想要计算每一次离队事件中,离队的同学的编号是多少。
      注意:每一个同学的编号不会随着离队事件的发生而改变,在发生离队事件后方阵中同学的编号可能是乱序的。
    Input
      输入文件名为 phalanx.in
      输入共 q+1 行。
      第 1 行包含 3 个用空格分隔的正整数 n, m, q,表示方阵大小是 n 行 m 列,一共发生了 q 次事件。
      接下来 q 行按照事件发生顺序描述了 q 件事件。每一行是两个整数 x, y,用一个空格分隔,表示这个离队事件中离队的学生当时排在第 x 行第 y 列。
    Output
      输出文件名为 phalanx.out。
      按照事件输入的顺序,每一个事件输出一行一个整数,表示这个离队事件中离队学生的编号。
    Sample Input
    2 2 3
    1 1
    2 2
    1 2
    Sample Output
    1
    1
    4
    Hint
    在这里插入图片描述

    线段树

    好像是第一次写这种线段树维护区间插入/删除的题(因为听说splay常数大,不敢写)。
    首先肯定将第m列与那n行分开维护,一共有n+1颗线段树。
    我们首先将对应的节点打上标记,表示该节点并没有改变,当我们需要访问其子区间的时候,将该区间拆成两个。然后询问(x,y)(x,y)(x,y)的时候,假设y!=my!=my!=m,那么就是找第x行的第y个数。否则就是找第m行的第x个数。找数的过程就是线段树上二分,具体来说我们对每个区间要记录一个sizesizesize表示区间内的人数。然后在将对应区间的sizesizesize减少。插入的时候直接插入在区间的最后就行了。
    每一行最多n+mn+mn+m个点,所以动态开点上界设在n+mn+mn+m就可以了。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<ctime>
    #include<queue>
    #include<iomanip>
    #define ll long long
    #define N 300005
    
    using namespace std;
    inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}
    
    ll n,m,q;
    int cnt;
    int nxt[N];
    const int lx=1,rx=N<<1;
    int rt[N];
    int tag[N*70],ls[N*70],rs[N*70],size[N*70];
    ll id[N*70];
    void update(int v) {size[v]=size[ls[v]]+size[rs[v]];}
    
    void build(int &v,int l,int r) {
        if(!v) v=++cnt;
        size[v]=r-l+1;
        if(l==r) id[v]=l;
        tag[v]=1;
    }
    
    void pre(int &v,int l,int r,int lx,int rx) {
        if(!v) v=++cnt;
        if(l>rx||r<lx) return ;
        if(l<=lx&&rx<=r) {build(v,lx,rx);return ;}
        int mid=lx+rx>>1;
        pre(ls[v],l,r,lx,mid);
        pre(rs[v],l,r,mid+1,rx);
        update(v);
    }
    
    void Find(int v,int lx,int rx,int k,ll &pos,ll &g) {
        if(lx==rx) {
            pos=lx;
            g=id[v];
            return ;
        }
        int mid=lx+rx>>1;
        if(tag[v]) {
            build(ls[v],lx,mid);
            build(rs[v],mid+1,rx);
            tag[v]=0;
        }
        if(k>size[ls[v]]) {
            Find(rs[v],mid+1,rx,k-size[ls[v]],pos,g);
        } else {
            Find(ls[v],lx,mid,k,pos,g);
        }
    }
    
    void Delete(int v,int lx,int rx,int pos) {
        size[v]--;
        if(lx==rx) return ;
        int mid=lx+rx>>1;
        if(tag[v]) {
            build(ls[v],lx,mid);
            build(rs[v],mid+1,rx);
            tag[v]=0;
        }
        if(pos<=mid) Delete(ls[v],lx,mid,pos);
        else Delete(rs[v],mid+1,rx,pos);
    }
    
    void Insert(int &v,int lx,int rx,int pos,ll id) {
        if(!v) v=++cnt;
        size[v]++;
        if(lx==rx) {
            ::id[v]=id;
            return ;
        }
        int mid=lx+rx>>1;
        if(tag[v]) {
            build(ls[v],lx,mid);
            build(rs[v],mid+1,rx);
            tag[v]=0;
        }
        if(pos<=mid) Insert(ls[v],lx,mid,pos,id);
        else Insert(rs[v],mid+1,rx,pos,id);
    }
    
    ll pos,g;
    
    void Get_out(ll &nx,ll &ny,ll x,ll y) {
        if(y<m) {
            Find(rt[x],lx,rx,y,pos,g);
            if(pos<=m-1) {
                nx=x;
                ny=pos;
            } else {
                nx=(g-1)/m+1;
                ny=(g-1)%m+1;
            }
            Delete(rt[x],lx,rx,pos);
        } else {
            Find(rt[n+1],lx,rx,x,pos,g);
            if(pos<=n) {
                nx=pos;
                ny=m;
            } else {
                nx=(g-1)/m+1;
                ny=(g-1)%m+1;
            }
            Delete(rt[n+1],lx,rx,pos);
        }
    }
    
    int main() {
        n=Get(),m=Get(),q=Get();
        if(m>1) {
            for(int i=1;i<=n;i++) {
                nxt[i]=m;
                pre(rt[i],1,m-1,lx,rx);
            }
        }
        pre(rt[n+1],1,n,lx,rx);
        nxt[n+1]=n+1;
        int x,y;
        ll sx,sy;
        ll tx,ty;
        while(q--) {
            x=Get(),y=Get();
            if(y<m) {
                Get_out(sx,sy,x,y);
                Get_out(tx,ty,x,m);
                Insert(rt[x],lx,rx,nxt[x],(tx-1)*m+ty);
                Insert(rt[n+1],lx,rx,nxt[n+1],(sx-1)*m+sy);
                nxt[x]++,nxt[n+1]++;
            } else {
                Get_out(sx,sy,x,y);
                Insert(rt[n+1],lx,rx,nxt[n+1],(sx-1)*m+sy);
                nxt[n+1]++;
            }
            cout<<(sx-1)*m+sy<<"
    ";
        }
        return 0;
    }
  • 相关阅读:
    中国历史朝代公元对照简表
    [Solved] DashBoard – Excel Service: The data sources may be unreachable, may not be responding, or may have denied you access.
    Delete/Remove Project from TFS 2010
    Sharepoint site showing system account instead of my username on the top right corner.
    你的成功在于你每天养成的习惯
    Internet Information Services is running in 32bit emulation mode. Correct the issue listed above and rerun setup.
    Prepare to back up and restore a farm (Office SharePoint Server 2007)
    Word中字号与磅值的对应关系
    How to: Change the Frequency for Refreshing the Data Warehouse for Team System
    UI Automation in WPF/Silverlight
  • 原文地址:https://www.cnblogs.com/hchhch233/p/9996737.html
Copyright © 2011-2022 走看看