CF701B 题解
题目分析:
这道题是给出了一个棋盘,大小为 $n×n$ 并且里面有 $m$ 个棋子,每个棋子可以攻击与他同一行,列的位置,并且 $n$ 和 $m$ 都很大,数据范围为 ( $1 \leq n \leq 100000, 1 \leq m \leq min(100000,n^{2} )$)。我们要输出每放一个棋子后,有多少个地方是攻击不到的。
题目难度:
个人认为在 普及/提高- 左右。
算法分析:
当看到这题的第一眼,我就想到了二维数组模拟,但是,在看了数据范围之后,发现行不通,二维数组绝对会爆,于是我就想到了 $stl$ 中的 $set$ 成员函数,下面我们来介绍一下什么是 $set$:
- 定义 $set$:
格式:$set <value_type> name;$
其中 $value_type$ 是 $set$ 中所要存储的元素类型,例如
int
,string
,或自定义的结构体名称。定义 $set$ 还要包含 $set$ 头文件,即
#include<set>
。
- 介绍 $set$
$set$ 的内部实现其实是一棵红黑树,
int
,string
等C++自带变量类型已经帮我们定义好了小于号,也就是他会自动帮我们进行排序,其中int
在 $set$ 中从小到大排,string
在 $set$ 中按字典序排。
- 使用 $set$
$set$ 有众多的内置函数,包括
insert(x)
,erase(x)
,empty()
,size()
,clear()
,find(x)
等等,下面让我们来介绍一下这些内置函数的作用。1.
insert(x)
/erase(x)
是在 $set$ 中 插入/删除 一个元素 $x$。2.
empty()
/size()
是判断 $set$ 是否为空/返回 $set$ 的元素个数。3.
clear()
清空一个 $set$ 的所有元素。4.
find(x)
查找 $set$ 中是否有 $x$ 这个元素。
了解了 $set$ 函数之后,就可以开始编写我们的程序了。
完整代码&解析:
#include<iostream>
#include<cstdio>
#include<set> //包含 set 的头文件
#define ll long long
using namespace std; //定义 long long 变量
ll n,m,a,b,ans;
int i;
int main() {
set<ll> set1,set2; //定义一个 $set$
set1.clear(); //把两个 $set$ 函数清空,具体见上面
set2.clear();
scanf("%lld%lld",&n,&m);//输入,注意要用 %lld
for(i=1; i<=m; ++i) {
scanf("%lld%lld",&a,&b); //输入,注意要用 %lld
set1.insert(a); //插入一个元素a
set2.insert(b); //插入一个元素b
ll len1=set1.size(),len2=set2.size(); //把 set1 和 set2 的长度分别赋值给 len1 和 len2
ans=n*n-len2*n-n*len1+len1*len2; //用公式计算答案 ans
printf("%lld ",ans); //输出,注意要用 %lld
}
}
希望本题解对大家有帮助,也感谢管理员百忙之中抽空为我审核题解,谢谢!