清理垃圾 set/栈/模拟
解题思路分析:
-
数据结构选择:
-
使用两个数组
vish和visl分别记录每行和每列的垃圾数量 -
使用两个栈数组
g和b分别存储每行和每列的垃圾位置信息 -
这种设计可以高效地进行查询和删除操作
-
-
处理流程:
-
初始化阶段:读取所有垃圾位置,统计每行每列的垃圾数量,并存储位置信息
-
查询处理阶段:
-
对于行查询(类型1):输出该行垃圾数后,清除该行所有垃圾,并同步更新对应列的计数
-
对于列查询(类型2):输出该列垃圾数后,清除该列所有垃圾,并同步更新对应行的计数
-
-
-
关键优化点:
-
使用栈存储位置信息,可以按照后进先出的顺序处理垃圾清除
-
每次清除操作都会同步更新行列计数,确保后续查询的正确性
-
max(0, count)确保即使重复查询已清除的行列也不会输出负数
-
-
复杂度分析:
-
时间复杂度:O(N + Q),每个垃圾和查询都只被处理一次
-
空间复杂度:O(N),与垃圾数量成正比
-
-
注意事项:
-
全局数组的大小需要根据题目约束设置足够大
-
使用栈结构可以高效处理清除操作,但要注意栈的操作顺序
-
输入数据量较大,使用scanf提高读取效率
-
这个解法通过合理的数据结构设计,实现了对大规模数据的高效处理,能够满足题目要求的性能约束。
#include<bits/stdc++.h> using namespace std; const int N = 2e5 + 10; // 定义最大可能的数据范围 // 定义全局变量: int vish[N], visl[N]; // vish[x]记录第x行的垃圾数量,visl[y]记录第y列的垃圾数量 stack<int> g[N], b[N]; // g[x]存储第x行的所有垃圾列号,b[y]存储第y列的所有垃圾行号 int n, m, k; // n行,m列,k个垃圾 int main() { // 输入网格基本信息和垃圾位置 cin >> n >> m >> k; for(int i = 1; i <= k; i++) { int x, y; scanf("%d%d", &x, &y); // 读取每个垃圾的位置 // 更新行和列的垃圾计数 vish[x]++; // 第x行垃圾数+1 visl[y]++; // 第y列垃圾数+1 // 将垃圾位置存入对应的行和列的栈中 g[x].push(y); // 第x行的垃圾所在列 b[y].push(x); // 第y列的垃圾所在行 } // 处理查询 int q; cin >> q; // 查询数量 while(q--) { int op, t; scanf("%d%d", &op, &t); // 读取查询类型和参数 // 类型1查询:处理行 if(op == 1) { // 输出该行的垃圾数量(确保非负) printf("%d\n", max(0, vish[t])); // 清除该行的垃圾计数 vish[t] = 0; // 遍历该行的所有垃圾,清除对应列的计数 while(g[t].size()) { int p = g[t].top(); // 获取该行的一个垃圾所在列 g[t].pop(); // 从栈中移除 visl[p]--; // 对应列的垃圾数-1 } } // 类型2查询:处理列 if(op == 2) { // 输出该列的垃圾数量(确保非负) printf("%d\n", max(0, visl[t])); // 清除该列的垃圾计数 visl[t] = 0; // 遍历该列的所有垃圾,清除对应行的计数 while(b[t].size()) { int p = b[t].top(); // 获取该列的一个垃圾所在行 b[t].pop(); // 从栈中移除 vish[p]--; // 对应行的垃圾数-1 } } } return 0; }

浙公网安备 33010602011771号