Unique Vision Programming Contest 2024 E - Paint

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 1H,W,M105
T i ∈ { 1 , 2 } T_i \in \{1,2\} Ti{1,2}
1 ≤ A i ≤ H 1 \leq A_i \leq H 1AiH for each i such that T i = 1 T_i=1 Ti=1
1 ≤ A i ≤ W 1 \leq A_i \leq W 1AiW 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 0Xi2×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;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值