B4229 棋盘 题解
1. 题意解释
给出一个
2. 思路
我们不难发现一开始的黑白网格可以看做是对全黑(或全白)图做奇数(或偶数)行列翻转得到。
我们考虑记录每行及每列的操作数。
考虑如何从行列中的操作数求出连通块个数。
不难发现每个连通块一定是呈方格状,且每个连通块一定对应一行上的连通块和一列上的连通块,所以我们只需要求出一行及一列的黑白连通块数,相乘即得到总的连通块数量。
对于一行(或一列)的连通块数,不难发现我们可以在每次操作时比较这一行(或这一列)操作的那个格子与其两边的格子颜色,然后就可以很简单的计算了。
3. 代码实现
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,q,op,a,row[100100],col[100100],rowcnt,colcnt;
signed main(){
cin>>n;
for(int i=2;i<=n;i+=2){
row[i]=col[i]=1;
}
cin>>q;
rowcnt=colcnt=n;
while(q--){
cin>>op>>a;
if(op==1){
if(a==1){
if(row[a]==row[a+1]){
rowcnt=min(rowcnt+1,n);
}
else{
rowcnt=max(rowcnt-1,1ll);
}
row[a]^=1;
}
else if(a==n){
if(row[a]==row[a-1]){
rowcnt=min(rowcnt+1,n);
}
else{
rowcnt=max(rowcnt-1,1ll);
}
row[a]^=1;
}
else{
if(row[a]==row[a+1]&&row[a]==row[a-1]){
rowcnt=min(rowcnt+2,n);
}
else if(row[a]!=row[a+1]&&row[a]!=row[a-1]){
rowcnt=max(rowcnt-2,1ll);
}
row[a]^=1;
}
}
if(op==2){
if(a==1){
if(col[a]==col[a+1]){
colcnt=min(colcnt+1,n);
}
else{
colcnt=max(colcnt-1,1ll);
}
col[a]^=1;
}
else if(a==n){
if(col[a]==col[a-1]){
colcnt=min(colcnt+1,n);
}
else{
colcnt=max(colcnt-1,1ll);
}
col[a]^=1;
}
else{
if(col[a]==col[a+1]&&col[a]==col[a-1]){
colcnt=min(colcnt+2,n);
}
else if(col[a]!=col[a+1]&&col[a]!=col[a-1]){
colcnt=max(colcnt-2,1ll);
}
col[a]^=1;
}
}
cout<<rowcnt*colcnt<<'\n';
}
return 0;
}