做题纪要

发布时间 2023-10-13 18:56:43作者: _bloss

Alice and Recoloring 1

有一个很牛逼的转化,考虑一个点 \(i,j\) 是否被以此为端点进行区间覆盖,只需考虑 \((i+1,j)\)\((i,j+1)\)\((i+1,j+1)\) 是为 \(B\) 的个数,如果个数为偶数,则此点不许操作,否则则需操作。设原序列 \(a_{i,j}=[s_{i,j}='B']\) , \(c_{i,j}=a_{i+1,j} \bigoplus a_{i,j+1} \bigoplus a_{i+1,j+1} \bigoplus a_{i,j}\),所以将 \(a\) 清空其实就是将 \(c\) 清空,而且还有一个比较好的地方就是进行操作一其实就是修改一个点,而进行操作四就是修改四个点形如:\((x+1,y+1)\) \(\rightarrow\) \((x,y)\)\((x,m)\)\((n,y)\)\((n,m)\),再考虑,操作 \(2,3\)就是在搞笑,完全可以被两次操作一代替,还有两次操作四可以被六次操作一代替,所以操作四最多进行一次,然后直接枚举那一次选在哪里就可以。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=505;
char s[N];
int c[N][N];
int a[N][N];
int sum[N][N];
signed main(){
    int n,m;
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%s",s+1);
        for(int j=1;j<=m;j++){
            if(s[j]=='B') c[i][j]=1;
            else c[i][j]=0;
        }
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            a[i][j]=(c[i][j]^c[i+1][j]^c[i][j+1]^c[i+1][j+1]);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
            sum[i][j]+=a[i][j]; 
        }
    }
    int ans=sum[n][m];
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            int w;
            w=a[n][m]+a[i-1][j-1]+a[n][j-1]+a[i-1][m];
            ans=min(ans,3+sum[n][m]-w+4-w);
        }
    }
    printf("%lld",ans);
}