3064: 【普及-】【P3913】车的攻击
内存限制:128 MB
时间限制:1.000 S
评测方式:文本比较
命题人:
提交:3
解决:3
题目描述
的国际象棋棋盘上有 个车,第个车位于第行,第 列。求至少被一个车攻击的格子数量。
车可以攻击所有同一行或者同一列的地方。
说明/提示
• 对于30% 的数据,;
• 对于60% 的数据,;
• 对于100% 的数据,。
输入
第1 行,2 个整数。
接下来K 行,每行2 个整数。
输出
1 个整数,表示被攻击的格子数量。
样例输入 复制
3 2
1 2
2 2
样例输出 复制
7
提示
首先考虑能不能直接将轴与轴有车的点先全部记录下来,然后将有车的行的数量和有车的列的数量记录下来,然后*再相加,但是这样显然不可行,因为这样会导致在行列交汇处的点呗重新算次。
既然被重新计算了,那我们把他们都删掉不就可以了吗?
不难看出,交叉点的个数就是有车的行数*有车的列数,那么就不难导出公式:
逆向思维,反着想,先找出所有不能被攻击的点,总的点数减去不能被攻击的点数,就是最少被一个车攻击的点数啦!
然后就是统计一共有几行几列有车了,这里就要用到我大中的一员大将:,也就是去重,通俗来讲,这个玩应的用法一般是
(数组名,数组名+大小)
(没错和几乎一模一样)
然后值得注意的有两点:
第一点:在之前必须保证去重数组有序,也就是得一下。
第二点:并不会生成一个新的数组,而是将原数组多余的部分“移”到了数组之后,同时本身还会返回一个指针,指向去重之后的最后一位。
利用可以指针相加减的特点,我们可以通过 -数组指针 来知道去重之后数组的“大小”
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int N = 1e6 + 10; LL n; //棋盘长、宽 int k; //注意这里要使用LL,使用int会有部分测试点WA, // 原因是后面的去重返回的是LL,如果这里有int,应该是会自动降为int导致出问题。 //行数组与列数组 int r[N], c[N]; int main() { //加快读取速度 ios::sync_with_stdio(false); cin.tie(); //棋盘的长宽和车的个数 cin >> n >> k; //读入车的位置 for (int i = 1; i <= k; i++) cin >> r[i] >> c[i]; //排序 sort(r + 1, r + k + 1); sort(c + 1, c + k + 1); //去重 LL x = unique(r + 1, r + k + 1) - r - 1; LL y = unique(c + 1, c + k + 1) - c - 1; printf("%lld", n * n - (n - x) * (n - y)); return 0; }