Comet OJ, "the bowl of Buddha's stone - unbreakable will" (difficult version)

meaning of the title

For a 010101 matrix, the number of global four connected blocks after covering one region at a time becomes 111.

Title Solution

The simplest way is violence, but it will time out. The complexity of violence is O(n3)O(n^3)O(n3).
Considering the redundant operation of violence, we need to change 111 into 111. In fact, we only need to change 000 into 1.

Next is the part of a more routine. It seems to have met before, but I didn't write this method.
For each row, create a parallel query set, pointing to the nearest 000 on your right. Each set is made up of one 000 as an ancestor and multiple 111.
Establish a connected join query set for join. Every time we get 000 from the union of each row and turn it into 111, we merge its four sides. Of course, the process of getting 000 also needs to determine whether it exceeds the right endpoint. ([y1,y2][y1,y2][y1,y2])

There are still a lot of details. It's worth learning.

#include<bits/stdc++.h>
using namespace std;
vector<int> v;

typedef long long ll;

const int Dr[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int ans,tot,n,m;
int ID[1050][1050],Fa[1050][1050],fa[1000050];
char s[1050][1050];

int find(int *f,int x){return f[x]==x?x:(f[x]=find(f,f[x]));}

void Handle(int x,int y){
    ans++;
    ID[x][y]=++tot,fa[tot]=tot;
    int u=find(Fa[x],y),v=find(Fa[x],y+1);
    if(u!=v)Fa[x][u]=v;
    for(int k=0;k<4;k++){
        int tx=x+Dr[k][0],ty=y+Dr[k][1];
        if(tx&&ty&&tx<=n&&ty<=m&&ID[tx][ty]){
            int l=find(fa,tot),r=find(fa,ID[tx][ty]);
            if(l!=r){
                ans--,fa[l]=r;
            }
        }
    }
}

int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)scanf("%s",s[i]+1);
    for(int i=1;i<=n;i++)for(int j=1;j<=m+1;j++)Fa[i][j]=j;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(s[i][j]=='1')Handle(i,j);
        }
    }
    int q;scanf("%d",&q);
    for(int i=1;i<=q;i++){
        int x1,y1,x2,y2;
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        for(int r=x1;r<=x2;r++){
            for(int c=find(Fa[r],y1);c<=y2;c=find(Fa[r],c))
                Handle(r,c);
        }
        printf("%d\n",ans);
    }
}

Posted by grimz on Sat, 26 Oct 2019 08:01:21 -0700