现在有一块玻璃,是长方形的(w 毫米× h 毫米),现在要对他进行切割。
切割的方向有两种,横向和纵向。每一次切割之后就会有若干块玻璃被分成两块更小的玻璃。在切割之后玻璃不会被移动。
现在想知道每次切割之后面积最大的一块玻璃是多少。
样例解释:
对于第四次切割,下面四块玻璃的面积是一样大的。都是2。
Input
单组测试数据。
第一行有三个整数 w,h,n (2≤w,h≤200000, 1≤n≤200000),表示玻璃在横向上长w 毫米,纵向上长h 毫米,接下来有n次的切割。
接下来有n行输入,每一行描述一次切割。
输入的格式是H y 或 V x。
H y表示横向切割,切割线距离下边缘y毫米(1≤y≤h-1)。
V x表示纵向切割,切割线距离左边缘x毫米(1≤x≤w-1)。
输入保证不会有两次切割是一样的。
Output
对于每一次切割,输出所有玻璃中面积最大的是多少。
Input示例
样例输入1
4 3 4
H 2
V 2
V 3
V 1
Output示例
样例输出1
8
4
4
2
思路:
并查集。可以先简化问题,比如只在水平方向进行切割,将高度每隔1个单位初始化rank为1,如果该点未被切割,则向下一个点进行合并,计算新的最大高度。最后将做法扩展到垂直方向即可。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long int ll;
const int MAXN = 2e5 + 10;
int w, h, n;
int input[MAXN];
bool isVer[MAXN];
bool visW[MAXN];
bool visH[MAXN];
int parentW[MAXN];
int parentH[MAXN];
int rankW[MAXN];
int rankH[MAXN];
int maxW;
int maxH;
ll result[MAXN];
char dir;
int findH(int x)
{
if (x != parentH[x])
{
parentH[x] = findH(parentH[x]);
}
return parentH[x];
}
void joinH(int x, int y)
{
x = findH(x);
y = findH(y);
if (x == y)
{
return;
}
parentH[x] = y;
rankH[y] += rankH[x];
maxH = max(maxH, rankH[y]);
}
int findW(int x)
{
if (x != parentW[x])
{
parentW[x] = findW(parentW[x]);
}
return parentW[x];
}
void joinW(int x, int y)
{
x = findW(x);
y = findW(y);
if (x == y)
{
return;
}
parentW[x] = y;
rankW[y] += rankW[x];
maxW = max(maxW, rankW[y]);
}
void init()
{
for (int i = 1; i <= w; i++)
{
parentW[i] = i;
rankW[i] = 1;
}
for (int i = 1; i <= h; i++)
{
parentH[i] = i;
rankH[i] = 1;
}
maxW = 1;
maxH = 1;
rankW[0] = 0;
rankH[0] = 0;
memset(visW, false, sizeof(visW));
memset(visH, false, sizeof(visH));
}
int main()
{
cin >> w >> h >> n;
init();
for (int i = 0; i < n; i++)
{
cin >> dir >> input[i];
if (dir == 'H')
{
isVer[i] = false;
visH[input[i]] = true;
}
else
{
isVer[i] = true;
visW[input[i]] = true;
}
}
for (int i = 1; i < w; i++)
{
if (!visW[i])
{
joinW(i, i + 1);
}
}
for (int i = 1; i < h; i++)
{
if (!visH[i])
{
joinH(i, i + 1);
}
}
for (int i = n - 1; i >= 0; i--)
{
result[i] = (ll)(maxH) * maxW;
if (isVer[i])
{
joinW(input[i], input[i] + 1);
}
else
{
joinH(input[i], input[i] + 1);
}
}
for (int i = 0; i < n; i++)
{
cout << result[i] << endl;
}
return 0;
}