CF1674 F. Desktop Rearrangement(二维转一维, 模拟)

大致题意 : 给定二维字符数组, '*'代表图标, '.'代表空白, 按照电脑桌面默认的图标排序方式进行排序(即先排第一列, 再排第二列, 以此类推) , 每次操作可以任意互换两个数组元素位置, 给定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;
    }
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值