CF1674 F.Desktop Rearrangement(模拟)

8 篇文章 0 订阅

传送门

这种小模拟题怎么能被评为 1800 的啊

题意

给定一个含有 0 0 0 1 1 1 的矩阵,需要将其中的 1 1 1 按电脑桌面进行排列(即每个 1 1 1 的左侧和上侧都为 1 1 1 ),每次可以选择桌面上的任意两点进行交换,问将矩阵变换成电脑桌面排列需要多少次操作。

预处理出在初始状况下共有多少个 1   ( c n t ) 1\ (cnt) 1 (cnt) ,以及有多少个 1   ( c o u n t ) 1\ (count) 1 (count) 处于不需要操作的范围内,则最终答案为 c n t − c o u n t cnt-count cntcount,由此所有询问可以通过 O ( 1 ) O(1) O(1) 解决

主要考虑两个问题: ① ① 添加或删除的点是否在不需要操作的范围内(需要首先更新范围), ② ② 添加或删除后对排列范围的最后一位是否产生了影响。对于问题 2 2 2,删除需要在范围更新前判断,增加需要在范围更新后判断。

#include <bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;

const int N=1010;
int g[N][N];

void solve(){
	int n,m,q;
	cin>>n>>m>>q;
	char op;
	int cnt=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>op;
			if(op=='.')
				g[i][j]=0;
			else
				g[i][j]=1,cnt++;
		}
	}
	
	int a=cnt/n,b=cnt%n;
	if(b==0&&a!=0){
		a--;
		b=n;
	}
	a++;
	
	int count=0;
	for(int j=1;j<a;j++)
		for(int i=1;i<=n;i++)
		 	if(g[i][j])
		 		count++;

	for(int i=1;i<=b;i++)
		if(g[i][a])
			count++;
	
	//cout<<cnt-count<<endl;
	
	for(int i=1;i<=q;i++){
		int x,y;
		cin>>x>>y;
		if(g[x][y]){//删除 
			cnt--;
			if(g[b][a])//原先该位置可以不移动 删除后需要移动 
				count--;
			g[x][y]=0;
			b--;
			if(b==0){
				b=n;
				a--;
			}
			if(y<a||y==a&&x<=b)//删除的是在无需移动范围内的 
				count--;
		}
		else{//增加 
			cnt++;
			b++;
			if(b==n+1){
				b=1;
				a++;
			}
			if(g[b][a])//原先该位置需要移动 添加后不需要移动
				count++;
				
			g[x][y]=1;
			if(y<a||y==a&&x<=b)//添加的是在无需移动范围内的 
				count++;
		}
		cout<<cnt-count<<endl;
	}
}

signed main(){
    ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);
    int t=1;
	//cin>>t;
    while(t--)
        solve();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值