
大意:
给你一个桌面状态,每次俩种操作桌面可以表示为一个大小为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;
}



















