CSUOJ 2022: Artwork 暴力 并查集

Description

A template for an artwork is a white grid of n × m squares. The artwork will be created by painting q horizontal and vertical black strokes. A stroke starts from square (x1, y1), ends at square (x2,y2)(x1=x2
or y1=y2)

and changes the color of all squares (x, y) to black where x1 ≤ x ≤ x2 and y1 ≤ y ≤ y2. The beauty of an artwork is the number of regions in the grid. Each region consists of one or more white squares that are connected to each other using a path of white squares in the grid, walking horizontally or vertically but not diagonally. The initial beauty of the artwork is 1. Your task is to calculate the beauty after each new stroke. Figure A.1 illustrates how the beauty of the artwork varies in Sample Input 1.
Input

The first line of input contains three integers n, m and q (1 ≤ n, m ≤ 1000, 1 ≤ q ≤ 104). Then follow q lines that describe the strokes. Each line consists of four integersx1,y1,x2
and y2(1 ≤ x1 ≤ x2 ≤ n, 1 ≤ y1 ≤ y2 ≤ m). Either x1 = x2 or y1=y2

(or both).
Output

For each of the q strokes, output a line containing the beauty of the artwork after the stroke.
Sample Input

4 6 5
2 2 2 6
1 3 4 3
2 5 3 5
4 6 4 6
1 6 4 6

Sample Output

1
3
3
4
3

题意:给出一个n列m行(md, 找bug找了半天 发现题目读错了)的矩阵 有Q次操作 操作会在x1 y1 到x2 y2的连线上设置一层障碍物,在每次操作后,输出当前联通块的个数。
解题思路:
既然要求输出联通块的个数,很容易联想到并查集,但是这里正着去遍历操作的话是没法用并查集写 因为有删除操作。如果强行正序遍历的话,每次操作就要遍历一次图 复杂度O(n*m*q) 。
考虑以逆序遍历操作。 这样就只有添加操作了。 最多1e4次操作 每次操作最多处理1000个点,每个点最多要与它周围的四个点进行合并操作。复杂度小于等于1e7 给了4秒 不会超时。

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include<iostream>
using namespace std;
typedef long long LL;
const int MAX=1e6 * 2;
int  n,m,q;
int fa[MAX];
int dirx[4]= {0,1,0,-1};
int diry[4]= {1,0,-1,0};
int maps[1005][1005];
int ans;
void init() {
    for(int i=0; i<MAX; i++) {
        fa[i]=i;
    }
}
int finds(int x) {
    if(fa[x]== x) {
        return x;
    } else {
        return fa[x]=finds(fa[x]);
    }
}
void unite(int x,int y) {
    x=finds(x);
    y=finds(y);
    if(x==y) return ;
    ans--;
    fa[y]=x;
}
void solve(int x,int y) {
    int tot=-1;
    for(int i=0; i<4; i++) {
        int cntx=x+dirx[i];
        int cnty=y+diry[i];
        if(!maps[cnty][cntx] && cntx<n && cnty<m && cntx>=0 && cnty>=0) {
            int cntid=cntx+cnty*n;
            unite(x+y*n,cntid);
        }
    }
}
void fiil(int x1,int y1,int x2,int y2,int p) {
    if(x1==x2) {
        for(int i=y1; i<=y2; i++) {
            maps[i][x1]+=p;
            if(!maps[i][x1]) {
                ans++;
                solve(x1,i);
            }
        }
    } else {
        for(int i=x1; i<=x2; i++) {
            maps[y1][i]+=p;
            if(!maps[y1][i]) {
                ans++;
                solve(i,y1);
            }
        }
    }
}
class node {
public:
    int x1,x2,y1,y2;
};
int main() {
    //freopen("01.in","r",stdin);
    node tmp;
    vector<node> V;
    vector<int> ansV;
    scanf("%d %d %d",&n,&m,&q);
    init();
    for(int i=0; i<q; i++) {
        scanf("%d %d %d %d",&tmp.x1,&tmp.y1,&tmp.x2,&tmp.y2);
        fiil(tmp.x1-1,tmp.y1-1,tmp.x2-1,tmp.y2-1,1);
        V.push_back(tmp);
    }
    //puts("++++++++++++++++++++++++++++++++++");
    for(int i=0; i<m; i++) {
        for(int j=0; j<n; j++) {
            if(!maps[i][j]) {
                ans++;
                solve(j,i);
                //cout<<ans<<endl;
            }
        }
    }
    ansV.push_back(ans);
    while(q--) {
        fiil(V[q].x1-1,V[q].y1-1,V[q].x2-1,V[q].y2-1,-1);
        ansV.push_back(ans);
    }
    for(int i=ansV.size()-2; i>=0; i--) {
        printf("%d\n",ansV[i]);
    }
}

猜你喜欢

转载自blog.csdn.net/lifelikes/article/details/79793682
今日推荐