洛谷题单指南-数学基础问题-P3913 车的攻击
原题链接:https://www.luogu.com.cn/problem/P3913
题意解读:车所在的行、列一共有多个个格子。
解题思路:
假设3*3的棋盘,有三个车
分析得知,三个车覆盖了第1、2两行,第2、3两列,覆盖的格子数用公式计算就是2 * 3 + 2 * 3 - 2 * 2 = 8
也就是两行格子数加两列格子数再减去交叉点。
因此,本题关键就是要统计一共有多少个不同的行R,多少个不同的列C,根据公司R*n+C*n-R*C即可得解。
由于n最大是10^9,用数组hash来去重不可取,可以用map来操作
80分代码:
#include <bits/stdc++.h>
using namespace std;
map<int, int> row, col;
int n, k, r, c;
int main()
{
scanf("%d%d", &n, &k);
for(int i = 1; i <= k; i++)
{
scanf("%d%d", &r, &c);
row[r]++;
col[c]++;
}
cout << row.size() * n + col.size() * n - row.size() * col.size();
return 0;
}
由于map在查找和插入时复杂度都是O(logN),因此上面代码复杂度为O(k*2logk),k最大10^6,复杂度约6*10^7,在加上map本身插入数据时还有logn的消耗,复杂度将超过6*10^7。
如果熟悉unordered_map,它在插入和查找的复杂度是O(1),替换map即可。
100分代码(unordered_map):
#include <bits/stdc++.h>
using namespace std;
unordered_map<int, int> row, col;
int n, k, r, c;
int main()
{
scanf("%d%d", &n, &k);
for(int i = 1; i <= k; i++)
{
scanf("%d%d", &r, &c);
row[r]++;
col[c]++;
}
cout << row.size() * n + col.size() * n - row.size() * col.size();
return 0;
}
如果不熟悉unordered_map,可以用两个vector把所有行、列存下来,进行去重,即可得一共覆盖了多少行、多少列。
要注意结果可能超int。
100分代码(排序去重):
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int row[N];
int col[N];
int n, k, r, c;
int main()
{
scanf("%d%d", &n, &k);
for(int i = 1; i <= k; i++)
{
scanf("%d%d", &r, &c);
row[i] = r;
col[i] = c;
}
sort(row + 1, row + k + 1); //对所有行排序
sort(col + 1, col + k + 1); //对所有列排序
long long R = 1, C = 1; //行、列数组的下标,用于去重
for(int i = 2; i <= k; i++)
{
if(row[i] != row[i - 1]) //对行数组去重
row[++R] = row[i];
if(col[i] != col[i - 1]) //对列数组去重
col[++C] = col[i];
}
cout << R * n + C * n - R * C;
return 0;
}
为什么用unordered_map的方法不需要定义long long呢,因为size()返回的类型是size_t,会根据机器自动适配,32位机器是int,64位机器就是long long。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?