【AtCoder】Beginner Contest 377-C.Avoid Knight Attack
Avoid Knight Attack
题目链接
Problem Statement
There is a grid of N 2 N^2 N2 squares with N N N rows and N N N columns. Let ( i , j ) (i,j) (i,j) denote the square at the i i i-th row from the top ( 1 ≤ i ≤ N ) (1\leq i\leq N) (1≤i≤N) and j j j-th column from the left ( 1 ≤ j ≤ N ) (1\leq j\leq N) (1≤j≤N).
Each square is either empty or has a piece placed on it. There are M M M pieces placed on the grid, and the k k k-th ( 1 ≤ k ≤ M ) (1\leq k\leq M) (1≤k≤M) piece is placed on square ( a k , b k ) (a_k,b_k) (ak,bk).
You want to place your piece on an empty square in such a way that it cannot be captured by any of the existing pieces.
A piece placed on square ( i , j ) (i,j) (i,j) can capture pieces that satisfy any of the following conditions:
- Placed on square ( i + 2 , j + 1 ) (i+2,j+1) (i+2,j+1)
- Placed on square ( i + 1 , j + 2 ) (i+1,j+2) (i+1,j+2)
- Placed on square ( i − 1 , j + 2 ) (i-1,j+2) (i−1,j+2)
- Placed on square ( i − 2 , j + 1 ) (i-2,j+1) (i−2,j+1)
- Placed on square ( i − 2 , j − 1 ) (i-2,j-1) (i−2,j−1)
- Placed on square ( i − 1 , j − 2 ) (i-1,j-2) (i−1,j−2)
- Placed on square ( i + 1 , j − 2 ) (i+1,j-2) (i+1,j−2)
- Placed on square ( i + 2 , j − 1 ) (i+2,j-1) (i+2,j−1)
Here, conditions involving non-existent squares are considered to never be satisfied.
For example, a piece placed on square ( 4 , 4 ) (4,4) (4,4) can capture pieces placed on the squares shown in blue in the following figure:
How many squares can you place your piece on?
中文题意
问题陈述
有一个由 N 2 N^2 N2 个正方形组成的网格,包含 N N N 行和 N N N 列。设 ( i , j ) (i,j) (i,j) 表示从上到下第 i i i 行 ( 1 ≤ i ≤ N ) (1\leq i\leq N) (1≤i≤N) 和从左到下第 j j j 列 ( 1 ≤ j ≤ N ) (1\leq j\leq N) (1≤j≤N) 处的正方形。
每个方块要么是空的,要么上面放着一个棋子。网格上有 M M M 个棋子, k k k 第 ( 1 ≤ k ≤ M ) (1\leq k\leq M) (1≤k≤M) 个棋子放置在 KaTeX parse error: Expected 'EOF', got '&' at position 4: (a &̲#95; k,b _ … 方格上。
你想把你的棋子放在一个空的正方形上,这样它就不会被任何现有的棋子所捕获。
放置在 ( i , j ) (i,j) (i,j) 方块上的棋子可以捕获满足以下任何条件的棋子:
- 放置在 ( i + 2 , j + 1 ) (i+2,j+1) (i+2,j+1) 方块上
- 放置在正方形 ( i + 1 , j + 2 ) (i+1,j+2) (i+1,j+2) 上
- 放置在 ( i − 1 , j + 2 ) (i-1,j+2) (i−1,j+2) 方框上
- 放置在 ( i − 2 , j + 1 ) (i-2,j+1) (i−2,j+1) 方块上
- 放置在 ( i − 2 , j − 1 ) (i-2,j-1) (i−2,j−1) 方块上
- 放置在正方形 ( i − 1 , j − 2 ) (i-1,j-2) (i−1,j−2) 上
- 放置在 ( i + 1 , j − 2 ) (i+1,j-2) (i+1,j−2) 方块上
- 放置在正方形 ( i + 2 , j − 1 ) (i+2,j-1) (i+2,j−1) 上
在这里,涉及不存在的正方形的条件被认为永远不满足。
例如,放置在方格 ( 4 , 4 ) (4,4) (4,4) 上的棋子可以捕获放置在下图中蓝色方格上的棋子:
你能把棋子放在几个方格上?
Constraints
- 1 ≤ N ≤ 1 0 9 1\leq N\leq10^9 1≤N≤109
- 1 ≤ M ≤ 2 × 1 0 5 1\leq M\leq2\times10^5 1≤M≤2×105
- 1 ≤ a k ≤ N , 1 ≤ b k ≤ N ( 1 ≤ k ≤ M ) 1\leq a_k\leq N,1\leq b_k\leq N\ (1\leq k\leq M) 1≤ak≤N,1≤bk≤N (1≤k≤M)
- ( a k , b k ) ≠ ( a l , b l ) ( 1 ≤ k < l ≤ M ) (a_k,b_k)\neq(a_l,b_l)\ (1\leq k\lt l\leq M) (ak,bk)=(al,bl) (1≤k<l≤M)
- All input values are integers.
Input
The input is given from Standard Input in the following format:
N N N M M M
a 1 a_1 a1 b 1 b_1 b1
a 2 a_2 a2 b 2 b_2 b2
⋮ \vdots ⋮
a M a_M aM b M b_M bM
Output
Print the number of empty squares where you can place your piece without it being captured by any existing pieces.
Sample Input 1
8 6
1 4
2 1
3 8
4 5
5 2
8 3
Sample Output 1
38
The existing pieces can capture pieces placed on the squares shown in blue in the following figure:
Therefore, you can place your piece on the remaining 38 38 38 squares.
Sample Input 2
1000000000 1
1 1
Sample Output 2
999999999999999997
Out of 1 0 18 10^{18} 1018 squares, only 3 3 3 squares cannot be used: squares ( 1 , 1 ) (1,1) (1,1), ( 2 , 3 ) (2,3) (2,3), and ( 3 , 2 ) (3,2) (3,2).
Note that the answer may be 2 32 2^{32} 232 or greater.
Sample Input 3
20 10
1 4
7 11
7 15
8 10
11 6
12 5
13 1
15 2
20 10
20 15
Sample Output 3
338
解法
这道题目大意,棋子的攻击位置是一个“日”字型的的走法,如果当前位置上有元素,则“日”字型的位置上都不能放元素。现在要我们统计还有多少个位置可以放元素。
使用八连通日字型分量的形式计算哪个位置不能放棋子,并且使用一个集合将所有不能放棋子的位置存起来。最后使用总的位置个数减去集合的长度就可以判断出有多少个位置还可以放棋子。
因为这道题可用的方格数量高达 1 0 18 10^{18} 1018 个,直接使用二维数组来存的话有可能会爆掉,所以我们使用一个集合来存储已经被占用的下标即可(以数对的形式存储)。
typedef long long LL;
LL n, m;
set<PII> s;
typedef pair<int, int> PII;
int dxr[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
int dyr[8] = {1, 2, 2, 1, -1, -2, -2, -1};void solved() {/* your code */cin >> n >> m;while(m --) {int x, y;cin >> x >> y;s.insert({x ,y});for (int i = 0; i < 8; i ++) {// 依次遍历八个方向int a = x + dxr[i], b = y + dyr[i];// 如果在范围内,就把下一个位置加入集合if(a > 0 && a <= n && b > 0 && b <= n) {s.insert({a, b});}}}// 答案等于棋盘大小 - 集合的长度cout << n * n - s.size() << endl;
}
总结
这道题于昨天的题相比数据明显要大,不能使用数组标记法去做,合理的使用唯一标记法,是我们做题的便捷手段。
这道题着重练习日字型八连通分量,题目不难,但思路重要。