Problem Statement
There is a grid with H rows and W columns. Initially, all cells are painted with color 0.
You will perform the following operations in the order i=1,2,…,M.
If T i = 1 T_i=1 Ti=1, repaint all cells in the A i A_i Ai-th row with color X i X_i Xi.
If T i = 2 T_i=2 Ti=2, repaint all cells in the A i A_i Ai-th column with color X i X_i Xi.
After all operations are completed, for each color i that exists on the grid, find the number of cells that are painted with color i.
Constraints
1
≤
H
,
W
,
M
≤
1
0
5
1 \leq H,W,M \leq 10^5
1≤H,W,M≤105
T
i
∈
{
1
,
2
}
T_i \in \{1,2\}
Ti∈{1,2}
1
≤
A
i
≤
H
1 \leq A_i \leq H
1≤Ai≤H for each i such that
T
i
=
1
T_i=1
Ti=1
1
≤
A
i
≤
W
1 \leq A_i \leq W
1≤Ai≤W for each i such that
T
i
=
2
T_i=2
Ti=2
0
≤
X
i
≤
2
×
1
0
5
0 \leq X_i \leq 2\times 10^5
0≤Xi≤2×105
All input values are integers.
思路
由于正向去考虑用哪个颜色涂哪一行时,会存在覆盖问题(即把之前上的色抹去),可以考虑采用逆向思维:从最后一个命令开始向前回滚,按此顺序,不会存在覆盖问题,只需要维护有多少行、列被上色了,以及某行是否已经被上色了即可。
Code
#include<iostream>
#include<cstring>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
typedef struct Instruction {
int t,a,x;
};
vector<Instruction> ins;
map<int,ll> mc;
bool paint_row[200005], paint_col[200005];
int main() {
ll h,w;
int m;
int t,a,x;
cin>>h>>w>>m;
for (int i=1;i<=m;i++) {
cin>>t>>a>>x;
ins.push_back({t,a,x});
}
ll row_cnt=0, col_cnt=0; // 已经涂了多少行、列
memset(paint_row,0,sizeof(paint_row));
memset(paint_col,0,sizeof(paint_col));
for (int i=m-1;i>=0;i--) {
if (ins[i].t==1&&!paint_row[ins[i].a]) { // 行
mc[ins[i].x] += w-col_cnt;
paint_row[ins[i].a] = true;
++row_cnt;
} else if (ins[i].t==2&&!paint_col[ins[i].a]){ // 列
mc[ins[i].x] += h-row_cnt;
paint_col[ins[i].a] = true;
++col_cnt;
}
}
ll cnt0 = h*w;
int color_num=0;
for (auto& item: mc) {
if (item.first!=0&&item.second!=0) {
cnt0 -= item.second;
++color_num;
}
}
mc[0] = cnt0;
cout << color_num+(cnt0!=0) << endl;
for (auto& item: mc) {
if (item.second!=0)
cout << item.first << ' ' << item.second << endl;
}
}