给出一个n*n的棋盘和k个点,再给出这k个点的坐标,每个点的斜对角四个方向所有位置都记标成黑块,求最后棋盘上还剩下多少白块?
In chess, a bishop is a piece, which attacks all fields of the chessboard, which are placed at same diagonal with it (in both diagonal directions).
On the chessboard N N Stefan placed M bishops. Now he wants to calculate number of fields, which are not attacked by any bishop.
Help Stefan to do it.
Input
First line of the input contains two integers N (1 N 106) and M (1 M 105) dimension of the chessboard and number of bishops, respectively. Then M lines follow. Each of those M lines contains two space-separated integers ri and ci 1-based numbers of row and column for i’th bishop (1 ri; ci N). No two bishops share the same field.
Output
Print one integer number of fields, which are not attacked by a bishop.
Example
standard input |
standard output |
10 6 |
33 |
4 7 |
|
8 5 |
|
8 7 |
|
6 2 |
|
9 7 |
|
8 4 |
|
#include <bits/stdc++.h> using namespace std; const int N = 1e6 + 5; int n,k; bitset< N<<1 > c,r; int nc[N], nr[N]; int main() { scanf("%d%d", &n, &k); // c.reset(); r.reset(); while(k--){ int x, y; scanf("%d%d", &x, &y); x--; y--; r[x+y] = 1; c[x+(n-1-y)] = 1; } long long ans = 0, sum[] = {0, 0}; for(int i = 0; i<n-1; i++) { nc[i] = c[i] + c[2*n-2-i]; //求长度为i+1的左斜段的个数 nr[i] = r[i] + r[2*n-2-i]; //求长度为i+1的右斜段的个数 ans += 1LL*(nc[i] + nr[i])*(i+1); //不考虑去重时黑格子个数 } nc[n-1] = c[n-1]; //i=2*n-2-i ,算出i=n-1,只能计算一次,所以拎出来 nr[n-1] = r[n-1]; ans += (nc[n-1]+nr[n-1])*n; //以右斜线为例,长度越长能交到的左斜线越多(有点贪心思想) //长度为1的右斜线只能交到长度为n的 //长度为2的右斜线只能交到长度为n-1的 //长度为3的右斜线只能交到长度为n和n-2的 //长度为4的右斜线只能交到长度为n-1和n-3的 //...... //累加操作即可。以i&1分开累加当前符合的左斜线个数,再乘上当前长度的右斜线个数。 for(int i = 0; i<n; i++) { sum[i&1] += nr[n-1-i]; ans -= sum[i&1]*nc[i]; } printf("%lld\n", 1LL*n*n-ans); return 0; }
有时候情况考虑多也很可怕。所以还是要仔细审题,想想是不是充分利用到了题目的条件来简化问题,不要读了两句就开始磨刀霍霍。。。