贡献题多考虑考虑差分吧🐺
题意:给定一个n*n大小的网格,上面有两种颜色黑和白,要求使用k*k的橡皮擦擦一次,输出最多的白线(全为白的行和列)数目。
这里的行与列其实互不影响,我们分别算出来行列然后相加就可以,
但是怎么判断一个左上角在(x,y)位置的橡皮擦能得到多少全白的行/列实在想不到了。。。
一开始想预处理出来每一行白块的个数(该题和个数关系不大),但是脑子稍微转一转就能想到没什么用啊摔!(ノ`Д)ノ
能维护的差不多就那么几样,对于每一行,应该找的是每一行最左边和最右边黑块的位置,这样才能判断出橡皮擦到底能不能覆盖全。
预处理完成之后,怎么计算答案也是个问题,知道这一行左右黑块的位置之后,就能知道完全覆盖该区域的橡皮擦都是那些,
对这些区域的橡皮擦,贡献加一,但是对整块答案直接加一太耗了,所以使用二维差分进行计算,最后加和。
#include<bits/stdc++.h>
using namespace std;
#define endll '\n'
#define C getchar()
typedef long long ll;
#define pi acos(-1.0)
#define INF 0x3f3f3f3f
#define mod 998244353
#define pii pair<int, int>
const int MAXN = 1e6 + 10;
#define stop system("pause")
#define lowbit(x) ((x) & (-x))
#define Temp template<typename T>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define mem(a, b) memset(a, b, sizeof(a))
#define fast std::ios::sync_with_stdio(false)
Temp inline void rd(T &s)
{
    s = 0;T t = 1, k = C;
    for (; k < '0' || k > '9'; k = C)if (k == '-') t = -1;
    for (; k >= '0' && k <= '9'; k = C) s = (s << 1) + (s << 3) + (k ^ 48);
    s *= t;
}
int n,k;
char mp[2222][2222];
int p[2222][2222];
void add(int x1,int y1,int x2,int y2)
{
    ++p[x1][y1],++p[x2+1][y2+1];
    --p[x1][y2+1],--p[x2+1][y1];
}
int main()
{
    rd(n),rd(k);
    for(int i=0;i<n;++i) scanf("%s",mp[i]);
    for(int i=0;i<n;++i)//每行
    {
        int b=-1,e=-1;
        for(int j=0;j<n;++j)
        {
            if(mp[i][j]=='B')
            {
                if(b==-1) b=j;
                e=j;
            }
        }
        if(b==-1) 
            add(0,0,n-1,n-1);//如果该行没有黑色,那么所有位置的橡皮贡献加一
        else if(e-b+1<=k)//橡皮大小足够覆盖
            add(max(0,i-k+1),max(0,e-k+1),i,b);//对能覆盖这片区域的橡皮擦贡献加一
    }
    for(int j=0;j<n;++j)//每列
    {
        int b=-1,e=-1;
        for(int i=0;i<n;++i)
        {
            if(mp[i][j]=='B')
            {
                if(b==-1) b=i;
                e=i;
            }
        }
        if(b==-1) 
            add(0,0,n-1,n-1);//如果该列没有黑色,那么所有位置的橡皮贡献加一
        else if(e-b+1<=k)//橡皮大小足够覆盖
            add(max(0,e-k+1),max(0,j-k+1),b,j);//对能覆盖这条区域的橡皮擦贡献加一
    }
    int ans=0;
    for(int i=0;i<n;++i)
        for(int j=1;j<n;++j)
            p[i][j]+=p[i][j-1];
    for(int i=1;i<n;++i)
        for(int j=0;j<n;++j)
            p[i][j]+=p[i-1][j];
    for(int i=0;i<n;++i)
        for(int j=0;j<n;++j)
            ans=max(ans,p[i][j]);
    cout<<ans<<endll;
    //stop;
    return 0;
}