这种小模拟题怎么能被评为 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 cnt−count,由此所有询问可以通过 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;
}