1 条题解

  • 0
    @ 2025-8-24 23:11:47

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar UniGravity
    好菜阿。

    搬运于2025-08-24 23:11:47,当前版本为作者最后更新于2025-07-28 16:56:56,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    对于这种题,一个常见的 trick 是考虑最上方和最下方的两条路径。

    发现修改后不合法当且仅当修改点在两条路径的并上。考虑动态维护两条路径。

    以维护最靠上路径为例(最靠下同理),考虑删去点的影响。

    d(i,j)d(i,j) 表示是否能从 (i,j)(i,j)(n,m)(n,m)。考虑从删除点往左上角 bfs 找出会修改哪些点的 d(i,j)d(i,j)。由于 d(i,j)d(i,j) 只会从 1100,因此直接做是 O(nm)O(nm) 的。

    发现答案路径上的一个区间被修改了,找出左端点后一直往下搜出新路径和右端点,然后删去原来路径即可。由于一个点只会加入路径和从路径删除一次,因此这部分还是 O(nm)O(nm) 的。

    时间复杂度 O(nm)O(nm)

    // Code by UniGravity
    #include<bits/stdc++.h>
    #define ll long long
    #define pii pair<int,int>
    #define forto(i,a,b) for(int i=(a),_##i(b);i<=_##i;i++)
    #define forbk(i,a,b) for(int i=(a),_##i(b);i>=_##i;i--)
    #define forv(i,a) for(int i(0),_##i(a);i<_##i;i++)
    #define fst first
    #define snd second
    #define il inline
    #define eb emplace_back
    #define mkp make_pair
    using namespace std;
    il int read(){
        int x=0,f=1;char c=getchar();
        while(c<'0'||'9'<c)c=='-'?(f=-1):0,c=getchar();
        while('0'<=c&&c<='9')x=x*10+c-'0',c=getchar();
        return x*f;
    }
    
    const int N=1005;
    int n,m,q;
    
    struct Path{
        bool tmp;
        int n,m,a[N][N];
        bool bk[N][N],pth[N][N];
        il void paint(){
            if(!tmp)return;
            cerr<<"------------------------------------------------\n";
            forto(i,1,n){
                forto(j,1,m)cerr<<a[i][j];
                cerr<<"  ";
                forto(j,1,m)cerr<<bk[i][j];
                cerr<<"  ";
                forto(j,1,m)cerr<<pth[i][j];
                cerr<<'\n';
            }
        }
        il void dfs(int x,int y){
            pth[x][y]=1;
            if(x==n&&y==m)return;
            if(bk[x][y+1])dfs(x,y+1);else dfs(x+1,y);
        }
        il void init(){
            bk[n][m]=1;
            forbk(i,n,1)forbk(j,m,1){
                if((i==n&&j==m)||a[i][j])continue;
                bk[i][j]=bk[i][j+1]||bk[i+1][j];
            }
            dfs(1,1);
            paint();
        }
        il pii dfs2(int x,int y){
            if(pth[x][y])return mkp(x,y);
            pth[x][y]=1;
            if(bk[x][y+1])return dfs2(x,y+1);else return dfs2(x+1,y);
        }
        pii ed;
        il void dfs3(int x,int y){
            pth[x][y]=0;
            if(mkp(x,y)==ed)return;
            if(pth[x-1][y])dfs3(x-1,y);else dfs3(x,y-1);
        }
        queue<pii>q;
        il void del(int x,int y){
            q.push(mkp(x-1,y)),q.push(mkp(x,y-1));
            a[x][y]=1,bk[x][y]=0;
            vector<pii>node;
            while(!q.empty()){
                int u=q.front().first,v=q.front().second;q.pop();
                if(u<1||v<1||!bk[u][v]||a[u][v])continue;
                bk[u][v]=bk[u+1][v]||bk[u][v+1];
                if(!bk[u][v])q.push(mkp(u-1,v)),q.push(mkp(u,v-1));
                else if(pth[u][v])node.eb(u,v);
            }
            paint();
            for(auto[u,v]:node){
                if(!pth[u][v+1]||bk[u][v+1])continue;
                pii t=dfs2(u+1,v);
                ed=mkp(u,v+1),dfs3(t.first-1,t.second);
            }
            paint();
        }
    }p1,p2;
    
    signed main(){
        n=read(),m=read();
        p1.n=n,p1.m=m,p2.n=m,p2.m=n;
        forto(i,1,n)forto(j,1,m)p1.a[i][j]=p2.a[j][i]=read();
        p1.init(),p2.init();
        q=read();
        queue<pii>que;
        while(q--){
            int x=read(),y=read();
            if(p1.pth[x][y]&&p2.pth[y][x])puts("0");
            else puts("1"),p1.del(x,y),p2.del(y,x);
        }
        return 0;
    }
    
    • 1

    信息

    ID
    11740
    时间
    2000ms
    内存
    512MiB
    难度
    (无)
    标签
    递交数
    0
    已通过
    0
    上传者