• bzoj5048: 塌陷的牧场


    Description

    农夫小Q将他的奶牛们饲养在一个长n宽m的矩形网格牧场中。行从上到下依次编号为1到n,列从左往右依次编号为1
    到m。为了防止奶牛们逃跑,小Q在牧场外圈安装了一排电网,只要奶牛走出这个n*m的矩形,就会触电死去。在牧
    场中,有e个格子塌陷了,一旦奶牛踩在上面,就会掉下去摔死。小Q为了饲养尽可能多的奶牛,在每个没有塌陷的
    格子上,都饲养着一头奶牛。tangjz偷走了小Q的口哨,并用口哨向奶牛们依次施放了q条指令,每条指令包含两个
    参数d和k,d表示上下左右之一的方向,k表示前进步数。发出指令后,每头奶牛都会听话地执行指令,甚至会因此
    丧生。所有奶牛移动完毕之后,tangjz才会施放下一条指令。请写一个程序统计每条指令中小Q损失了多少头奶牛

    Input

    第一行包含4个正整数n,m,e,q(1<=n,m,q<=2000,0<=e<=min(nm,2000))
    分别表示牧场的长宽、塌陷的格子数以及指令数。
    接下来e行,每行两个正整数x_i,y_i(1<=x_i<=n,1<=y_i<=m)
    表示每个塌陷格子的坐标。输入数据保证每个格子不会被描述多次。
    接下来q行,每行包含一个字符d和一个正整数k(1<=k<=2000)
    描述每条指令。其中UDLR分别表示上下左右。

    Output

    输出q行,每行一个整数,即第i条指令中损失的奶牛数量。

    塌陷的格子数和询问数都很少,可以反过来移动这些格子来计算每次新覆盖了多少位置,查询区间内未被覆盖的位置可以用zkw线段树实现,时间复杂度O(qelog(n+m)+nm)。

    #include<bits/stdc++.h>
    const int N=2055;
    int n,m,e,q,mx;
    int xs[N],ys[N],dc=0,tr[2][N][N*2],ds[N*N],dp=0,*t,Q[N];
    bool dd[N][N];
    void del(int x,int y){
        if(!dd[x][y])dd[x][y]=1,++dc;
    }
    void chk(int*t,int x){
        for(int w=x;w>1&&!t[w^1];t[w>>=1]=0);
        int ql=0,qr=0;
        t[x]=0,Q[++qr]=x;
        while(ql!=qr){
            int w=Q[++ql];
            if(w>=mx)ds[dp++]=w-mx;
            else{
                w<<=1;
                if(t[w])t[w]=0,Q[++qr]=w;
                ++w;
                if(t[w])t[w]=0,Q[++qr]=w;
            }
        }
    }
    void dt(int*t,int l,int r){
        for(l+=mx-1,r+=mx+1;r-l!=1;l>>=1,r>>=1){
            if(~l&1&&t[l+1])chk(t,l+1);
            if(r&1&&t[r-1])chk(t,r-1);
        }
    }
    void dlr(int x,int l,int r){
        if(x<1||x>n)return;
        if(r>m)r=m;if(l<1)l=1;
        if(l<=r)dt(tr[0][x],l,r);
        for(;dp;del(x,ds[--dp]));
    }
    void dud(int y,int l,int r){
        if(y<1||y>m)return;
        if(r>n)r=n;if(l<1)l=1;
        if(l<=r)dt(tr[1][y],l,r);
        for(;dp;del(ds[--dp],y));
    }
    void init(int*t,int c){
        for(int i=1;i<=c;++i)t[mx+i]=1;
        for(int i=mx-1;i;--i)t[i]=t[i<<1]|t[(i<<1)+1];
    }
    int main(){
        scanf("%d%d%d%d",&n,&m,&e,&q);
        for(mx=1;mx<=std::max(n,m)+5;mx<<=1);
        for(int i=1;i<=e;++i)scanf("%d%d",xs+i,ys+i),del(xs[i],ys[i]);
        for(int i=1;i<=n;++i)init(tr[0][i],m);
        for(int i=1;i<=m;++i)init(tr[1][i],n);
        int lp=0,rp=m+1,up=0,dp=n+1;
        while(q--){
            char dir;
            int d,v0=dc;
            scanf(" %c%d",&dir,&d);
            if(dir=='R'){//m-
                for(int i=1;i<=e;++i)dlr(xs[i],ys[i]-d,ys[i]),ys[i]-=d;
                for(int i=1;i<=n;++i)dlr(i,rp-d,rp);
                lp-=d,rp-=d;
            }
            if(dir=='L'){//m+
                for(int i=1;i<=e;++i)dlr(xs[i],ys[i],ys[i]+d),ys[i]+=d;
                for(int i=1;i<=n;++i)dlr(i,lp,lp+d);
                lp+=d,rp+=d;
            }
            if(dir=='D'){//n-
                for(int i=1;i<=e;++i)dud(ys[i],xs[i]-d,xs[i]),xs[i]-=d;
                for(int i=1;i<=m;++i)dud(i,dp-d,dp);
                up-=d,dp-=d;
            }
            if(dir=='U'){//n+
                for(int i=1;i<=e;++i)dud(ys[i],xs[i],xs[i]+d),xs[i]+=d;
                for(int i=1;i<=m;++i)dud(i,up,up+d);
                up+=d,dp+=d;
            }
            printf("%d
    ",dc-v0);
        }
        return 0;
    }
  • 相关阅读:
    JavaScrip中构造函数、prototype原型对象、实例对象三者之间的关系
    (字符缓冲流)文本排序案例
    Annotation注解的应用(打印异常信息)
    Annotation(注解)
    Java关键技术强化
    基本数据类型与引用数据类型的区别
    EKT反射
    bootstrap的概念
    Servlet强化
    java数据库连接池
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7691098.html
Copyright © 2020-2023  润新知