大致题意 : 给定二维字符数组, '*'代表图标, '.'代表空白, 按照电脑桌面默认的图标排序方式进行排序(即先排第一列, 再排第二列, 以此类推) , 每次操作可以任意互换两个数组元素位置, 给定q次查询, 每次查询为一个下标, 并会将该下标取反(图标变空白, 空白变图标), 问每次查询的最小操作次数
思路 : 将二维数组以列为一维进行二维转一维, 对一维字符串进行模拟分类讨论即可
代码及其注释 :
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <iterator>
#include <cmath>
#include <algorithm>
#include <sstream>
#include <map>
#include <stack>
#include <set>
#include <queue>
#include <iomanip>
using namespace std;
stringstream ss;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e3+10;
const int INF = 0x3f3f3f3f;
int n,m,q;
char g[N][N], a[N*N];
int main()
{
scanf("%d%d%d", &n, &m, &q);
int cnt = 0;
for(int i = 1; i<=n; i++)
{
for(int j = 1; j<=m; j++)
{
cin>>g[i][j];
if(g[i][j] == '*') cnt ++;
a[(j-1)*n+i] = g[i][j];
}
}
int ans = 0;
// 以列为维度转化为一维数组进行处理, ans为需要移动的图标
for(int i = cnt+1; i<=n*m; i++) if(a[i] == '*') ans ++;
while(q -- )
{
int x,y,cur;
cin>>x>>y;
// 位置转换为1维数组
cur = (y-1)*n+x;
// 若当前位置为图标, 则图标总数减小, 图标总数减少会导致图标排序后的最大值减少(即合法范围会变动)
// 通过减少前的合法范围来进行判断极限位置处的变动,是否需要移动的图标(答案)会增加,判断后减少图标总数
// 如 **.*...*. 若当前位置为倒数第二颗'*',初始ans为1(即当前这颗),
// 当当前这颗'*'变为'.'后,ans--, 但'*'的总数cnt减少, cnt为3,
// 导致原本合法的第四位置上(即原来合法范围的最大值)的'*'会不合法,ans++,
if(a[cur] == '*')
{
a[cur] = '.';
if(cur > cnt) ans --;
if(cur != cnt && a[cnt] == '*') ans ++;
cnt --;
}
else{
// 若当前位置为空白, 则图标总数增加, 通过增加后的合法范围来判断极限位置处的变动,
// 同理上一种情况, 不过这种判断需要先变动合法范围,
// 因为合法范围增大影响的是增大后的最大位置, 合法范围减小影响减小前的最大位置
a[cur] = '*';
cnt++;
if(cur > cnt) ans++;
if(cur != cnt && a[cnt] == '*') ans --;
}
cout<<ans<<endl;
}
}