超级传送门:
http://acm.hdu.edu.cn/showproblem.php?pid=4146
有一个棋盘,有黑白两色棋子布满棋盘,黑色是b,白色是w。棋盘从左至右编号1~N,从上至下编号1~N,然后执行一系列命令(Xi,Xj),反转第Xi行和第Xj列,可以看出处在(Xi,Xj)这个点上的棋子被反转了两次,所以没变。题目要求输出执行一系列指令后棋盘上剩余的白子数目。
题目数据量 (1 <= N <= 1000, 0 <= Q <= 100000),如果直接用模拟法,每条指令都遍历一下该行和该列并反转,那么很容易TLE。可以用两个数组来记录每行和每列被反转的次数,如果该点所在的行和列的翻转次数之和是偶数,则该点保持原状,否则的话就变反,如此可节约时间,但还是相当暴力。
#include<stdio.h>
#include<string.h>
int map[1050][1050];
int Qa[100010],Qb[100010];
int main () {
//freopen("1.txt","r",stdin);
int t,n,q,qa,qb,i,j,k,sum,len;
char temp[1050];
scanf("%d",&t);
for (i=0;i<t;i++) {
memset(map,0,sizeof(map));
memset(Qa,0,sizeof(Qa));
memset(Qb,0,sizeof(Qb));
scanf("%d",&n);
sum = 0;
for (j=1;j<=n;j++) {
scanf("%s",temp);
len = strlen(temp);
for (k=0;k<len;k++) {
if (temp[k]=='b') map[j][k+1] = 0;
else if (temp[k]=='w') map[j][k+1] = 1;
}
}
scanf("%d",&q);
for (j=0;j<q;j++) {
scanf("%d%d",&qa,&qb);
Qa[qa] ++;
Qb[qb] ++;
}
for (j=1;j<=n;j++) {
for (k=1;k<=n;k++) {
if ((Qa[j]+Qb[k])%2==0 && map[j][k]) sum ++;
if ((Qa[j]+Qb[k])%2==1 && !map[j][k]) sum ++;
}
}
printf("Case #%d: %d\n",i+1,sum);
}
return 0;
}