Atcoder Beginner Contest 179F - Simplified Reversi 解题报告

Atcoder Beginner Contest 179F - Simplified Reversi 解题报告

1 题目链接

传送门

2 题目大意

题目:Simplified 黑白棋
题目大意:

有一个边长为 N N N 正方形的网格, ( i , j ) (i,j) (i,j) 为第 i i i 行第 j j j 列的正方形。

网格中央 ( N − 2 ) × ( N − 2 ) (N − 2)\times(N − 2) (N2)×(N2) 的每个方格上都有一个黑色的石头。底部和右侧的方格中,每个方格上都有一块白色的石头。

给出了 Q Q Q 个查询,有两种查询。它们的输入格式和描述如下:

  • ( 1 , x ) (1,x) (1,x) 上放一个白色石头。之后,对于 ( 1 , x ) (1,x) (1,x) ( 1 , x ) (1,x) (1,x) 之间的每一个黑色石头,如果你从 ( 1 , x ) (1,x) (1,x) 开始,用白色石头替换它。
  • ( x , 1 ) (x,1) (x,1) 上放一个白色石头。之后,对于 ( x , 1 ) (x,1) (x,1) ( x , 1 ) (x,1) (x,1) 之间的每一个黑色石头,如果你从 ( x , 1 ) (x,1) (x,1) 开始,你击中的第一个白色石头,用白色石头替换它。

在处理完所有 Q Q Q 次查询后,网格上有多少黑色石头?

3 解法分析

提供一种不用数据结构的思路。

先把格局打开,把它想成一道思维题。

假设某一黑色区域宽为 x x x,长为 y y y,我们考虑一种修改,比如 1    k 1\ \ k 1  k

不难发现修改后对 [ k + 1 , y ] [k+1,y] [k+1,y] 1 1 1 操作,都是固定的减去 x x x

2 2 2 操作同理。

每操作一次都将黑色区域的长宽进行缩小,并用数组记录减少的黑色方块数即可。

4 AC Code

#include 
#define rep(i, a, b) for (int (i) = (a); (i) <= (b); ++(i))
#define fep(i, a, b) for (int (i) = (a); (i) < (b); ++(i))
#define int long long
#define N 200007
using namespace std;

int ans;
int n, q;
int x, y;
int opt, k;
int r[N],c[N];

signed main() {
	scanf("%lld%lld", &n, &q);
	x = y = n;
	ans = (n - 2) * (n - 2);
	while (q--) {
		scanf("%lld%lld", &opt, &k);
		if (opt == 1) {
			if (k < y) {
				ans -= x - 2;
				while (y > k)
					c[y--] = x - 2;
			}
			else
				ans -= c[k];
		}
		else {
			if (k < x) {
				ans -= y - 2;
				while (x > k)
					r[x--] = y - 2;
            }
			else
				ans -= r[k];
		}
	}
	printf("%lld\n", ans);
	return 0;
}

你可能感兴趣的:(Atcoder,Beginner,Contest,c++)