ArtWork(并查集+降维)

                                              ArtWork

                                                                 时间限制: 4 Sec  内存限制: 128 MB
                                                                                提交: 51  解决: 24
                                                                [提交] [状态] [讨论版] [命题人:外部导入]

题目描述

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 (x 1 , y 1 ), ends at square (x 2 , y 2 ) (x 1 = x 2 or y 1 = y 2 ) and changes the color of all squares (x, y) to black where
x 1 ≤ x ≤ x 2 and y 1 ≤ y ≤ y 2 .

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.

 

输入

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 integers x 1 , y 1 , x 2 and y 2 (1 ≤ x 1 ≤ x 2 ≤ n, 1 ≤ y 1 ≤ y 2 ≤ m). Either x 1 = x 2 or y 1 = y 2 (or both).

输出

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

样例输入

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

样例输出

1
3
3
4
3

                                                                          [提交]     [状态]

题意:

题意是给你一个n*m的矩阵,q次询问,每次将连续的一些竖直或水平的格子染黑,问每一步操作之后白色联通块的个数

题解:

从最后一种局面往前走,先求出所有操作之后白色联通块的数量,然后逐条删去黑线,对新出现的白格子,要么和原有的某个联通块相连,要么属于单独的联通块 用并查集维护联通块  注意降维操作 将二维数组降为一维

#include<stdio.h>
#include<string.h>
#define MAXN 1010
struct stock
{
    int x1, x2, y1, y2;
} pos[10010];

int vis[MAXN*MAXN], fa[MAXN*MAXN],ans[10010];//vis表示当前位置是黑还是白 0表示白色 1表示黑色 ans[n]表示第n次画横线时白色连通块的个数
int dir[4][2] = { 0, 1, -1, 0, 0, -1, 1, 0 };
int m, n, p,t;
int Hash(int x, int y)//用哈希表表示  将矩阵转换成一行 降维
{
    int sum = (x - 1)*m + y;
    return sum;
}
void init()//初始化
{
    for (int i = 1; i <= n*m; i++)
    {
        fa[i] = i;
        vis[i] = 0;
    }
}
int Find(int x)
{
    return x == fa[x] ? x : fa[x] = Find(fa[x]);
}
void join(int x, int y)//将两个相邻连通块连接在一起
{
    int fx = Find(x), fy = Find(y);
    if (fx == fy)
        return;
    fa[fx] = fy;
    t--;//t表示连通块个数
}
int check(int x, int y)
{
    if (x >= 1 && y >= 1 && x <= n&&y <= m)
        return 1;
    return 0;
}
void work(int x,int y)//将刚出现的白块连到连通块中
{
    for (int i = 0; i < 4; i++)
    {
        int xx = x + dir[i][0];
        int yy = y + dir[i][1];
        if (check(xx, yy) && !vis[Hash(xx,yy)])
            join(Hash(xx,yy), Hash(x,y));

    }
}
int main()
{
    scanf("%d %d %d", &n, &m, &p);
    t = m*n;
    init();
    //画黑线
    for (int i = 1; i <= p; i++)
    {
        scanf("%d%d%d%d", &pos[i].x1, &pos[i].y1, &pos[i].x2, &pos[i].y2);
        for (int x = pos[i].x1; x <= pos[i].x2; x++)
        {
            for (int y = pos[i].y1; y <= pos[i].y2; y++)
            {
                if (vis[Hash(x, y)] == 0)
                    t--;
                vis[Hash(x, y)]++;
            }
        }
    }

    //求出最后一个图的白色连通块的个数
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            if (!vis[Hash(i,j)])work(i, j);

    //向前面的图推
    for (int i = p; i > 0; i--)
    {
        ans[i] = t;
        //一步一步撤去黑线
        for (int x = pos[i].x1; x <= pos[i].x2; x++)
        {
            for (int y = pos[i].y1; y <= pos[i].y2; y++)
            {
                vis[Hash(x, y)]--;
                if (vis[Hash(x, y)] == 0)
                {
                    t++;//黑块撤完白块数目增加
                    work(x, y);
                }
            }
        }
    }
    for (int i = 1; i <= p; i++)printf("%d\n", ans[i]);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41021816/article/details/82990086
今日推荐