• 列队


    传送门

    解法:

    a11 a12 a13
    a21 a22 a23
    a31 a32 a33

    我们发现移走一个点只会影响
    该点所在行
    以及最后一列
    所以很容易能想到维护每一行以及最后一列
    每次删两个点,加两个点
    并用动态开点线段树维护

    删点方法:

    对线段树中每个节点处理子节点个数
    记作sz[k]
    递归找到要删的节点(设在线段树中位置为k)
    使k位置及k位置所有父节点的sz[]-1
    搜取值时就用sz[]作为判断递归条件
    这样 要被删掉的点永远不可能被访问
    相当于被删除了

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<cmath>
    #include<queue>
    #include<map>
    #define inf 2000000000
    #define min(x,y) ((x)<(y)?(x):(y))
    #define max(x,y) ((x)>(y)?(x):(y))
    #define rep(i,a,b) for(int i=(a);i<=(b);++i)
    #define dwn(i,a,b) for(int i=(a);i>=(b);--i)
    using namespace std;
    typedef long long ll;
    int n,m,now,q,p;
    int tot=0,o[300010],root[300010],sz[10000010],tl[10000010],tr[10000010];
    ll t,val[10000010];
    inline int build()
    {
        tot++;
        tl[tot]=tr[tot]=val[tot]=0;
        return tot;
    }
    inline int get_sz(int l,int r)
    {
        if(now==n+1)
        {
            if(r<=n) return r-l+1;
            if(l<=n) return n-l+1;
            return 0;
        }
        if(r<m) return r-l+1;
        if(l<m) return m-l;
        return 0;
    }
    ll ask_val(int &k,int l,int r,int x)
    {
        if(!k)
        {
            k=build();
            sz[k]=get_sz(l,r);
            if(l==r)
            {
                if(now==n+1) val[k]=1ll*l*m;
                else val[k]=1ll*(now-1)*m+l;
            }
        }
        sz[k]--;
        if(l==r) return val[k];
        int mid=(l+r)>>1;
        if(x<=sz[tl[k]]||(!tl[k]&&x<=(mid-l+1))) return ask_val(tl[k],l,mid,x);
        else{
            if(!tl[k]) x=x-(mid-l+1);
            else x=x-sz[tl[k]];
            return ask_val(tr[k],mid+1,r,x);
        }
    }
    void update(int &k,int l,int r,int x,ll v)
    {
        if(!k)
        {
            k=build();
            sz[k]=get_sz(l,r);
            if(l==r) val[k]=v;
        }
        sz[k]++;
        if(l==r) return;
        int mid=(l+r)>>1;
        if(x<=mid) update(tl[k],l,mid,x,v);
        else update(tr[k],mid+1,r,x,v);
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&q);
        p=max(n,m)+q;
        rep(i,1,q)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            if(y==m)
            {
                now=n+1;
                t=ask_val(root[n+1],1,p,x);
            }
            else
            {
                now=x;
                t=ask_val(root[x],1,p,y);
            }
            printf("%lld
    ",t);
            if(y==m)
            {
                o[n+1]++;
                update(root[n+1],1,p,n+o[n+1],t);
            }
            else
            {
                now=n+1;
                o[n+1]++;
                update(root[n+1],1,p,n+o[n+1],t);
                t=ask_val(root[n+1],1,p,x);
                now=x;
                o[x]++;
                update(root[x],1,p,m-1+o[x],t);
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    docker compose 笔记
    一个简单的计划
    译Node.js应用的持续部署
    Javascript中的字典和散列
    施耐德保护调试技巧
    施耐德Sepam 40系列备自投逻辑
    请随时告诉自己
    顺其自然
    启用
    我们能做的是......
  • 原文地址:https://www.cnblogs.com/MYsBlogs/p/10990805.html
Copyright © 2020-2023  润新知