大意:
给你一个桌面状态,每次俩种操作桌面可以表示为一个大小为n×m的矩形矩阵,由字符'.'(桌面上的空单元格)和'*'(一个图标)组成。
操作:
输入<x,y>表示改变其状态的单元格的位置(如果该单元格以前包含图标,则图标被移除,否则,在该单元格中出现一个图标)。
输出:
在该状态桌面下达到合法状态的最小移动次数
#include<iostream>
#include<algorithm>
#include<vector>
#include<bitset>
#include<cmath>
#include<set>
#include<climits>
#include<map>
#include<cstring>
using i64 = int64_t;
using namespace std;
#define endl '\n'
//#define int i64
const int maxn = 1e3 + 10;
char G[maxn][maxn];
int sum[maxn * maxn];//前 i 个位置共有多少个 * 号
int n,m,cnt = 0;
int x, y;
int lowbit(int x)
{
return x & -x;
}
void add(int x, int c)
{
for(; x <= n * m; x += lowbit(x)) sum[x] += c;
}
int ask(int x)
{
int res = 0;
for (; x; x -= lowbit(x)) res += sum[x];
return res;
}
int get(int x, int y)
{// 以列为单位映射
return (y - 1) * n + x;
}
void solve()
{
scanf("%d %d",&x,&y);
int t = get(x, y);
if(G[x][y] == '*')
{
G[x][y] = '.';
add(t, -1);
cnt --;
}
else
{
G[x][y] = '*';
add(t, 1);
cnt++;
}
// for(int i = 1; i <= n; i ++ ){
// for(int j = 1; j <= m; j ++ )
// cout << G[i][j];
// cout << endl;
// }
// cout << cnt << endl;
cout << cnt - ask(cnt) << endl;
}
signed main()
{
//cin.tie(0) -> sync_with_stdio(false);
int T = 1;
cin >> n >> m >> T;
for(int i = 1; i <= n; i++)
scanf("%s", G[i] + 1);
for(int i = 1; i <= n; i ++ )
for(int j = 1; j <= m; j ++ )
if(G[i][j] == '*') add(get(i, j), 1), cnt++;
while(T--)
solve();
return 0;
}