CodeForce Round 578 Div 2 D. White Lines

D. White Lines

Problem

Gildong has bought a famous painting software cfpaint. The working screen of cfpaint is square-shaped consisting of \(n\) rows and \(n\) columns of square cells. The rows are numbered from \(1\) to \(n\), from top to bottom, and the columns are numbered from \(1\) to \(n\), from left to right. The position of a cell at row \(r\) and column \(c\) is represented as \((r,c)\). There are only two colors for the cells in cfpaint — black and white.

There is a tool named eraser in cfpaint. The eraser has an integer size \(k (1 \leq k \leq n)\). To use the eraser, Gildong needs to click on a cell \((i,j)\) where \(1 \leq i,j \leq n−k+1\). When a cell \((i,j)\) is clicked, all of the cells \((i′,j′)\) where \(i \leq i′ \leq i+k−1\) and \(j \leq j′ \leq j+k−1\) become white. In other words, a square with side equal to \(k\) cells and top left corner at \((i,j)\) is colored white.

A white line is a row or a column without any black cells.

Gildong has worked with cfpaint for some time, so some of the cells (possibly zero or all) are currently black. He wants to know the maximum number of white lines after using the eraser exactly once. Help Gildong find the answer to his question.

Input

The first line contains two integers \(n\) and \(k (1 \leq k \leq n \leq 2000)\) — the number of rows and columns, and the size of the eraser.

The next \(n\) lines contain \(n\) characters each without spaces. The \(j^{th}\) character in the \(i^{th}\) line represents the cell at \((i,j)\). Each character is given as either 'B' representing a black cell, or 'W' representing a white cell.

Output

Print one integer: the maximum number of white lines after using the eraser exactly once.

Examples

input

4 2
BWWW
WBBW
WBBW
WWWB

output

4

input

3 1
BWB
WWB
BWB

output

2

input

5 3
BWBBB
BWBBB
BBBBB
BBBBB
WBBBW

output

2

input

2 2
BW
WB

output

4

input

2 1
WW
WW

output

4

Note

In the first example, Gildong can click the cell \((2,2)\), then the working screen becomes:

BWWW
WWWW
WWWW
WWWB

Then there are four white lines — the \(2^{nd}\) and \(3^{rd}\) row, and the \(2^{nd}\) and \(3^{rd}\) column.

In the second example, clicking the cell \((2,3)\) makes the \(2^{nd}\) row a white line.

In the third example, both the \(2^{nd}\) column and \(5^{th}\) row become white lines by clicking the cell \((3,2)\).

想法 (官方题解)

Let's consider a single row that contains at least one black cell. If the first appearance of a black cell is at the \(l^{th}\) column and the last appearance of a black cell is at the \(r^{th}\) column, we can determine whether it becomes a white line when a certain cell \((i,j)\) is clicked in \(O(1)\), after some preprocessing. It becomes a white line if and only if a cell \((i,j)\) is clicked where the row is at \([i,i+k−1]\) and \(j \leq l \leq r \leq j+k−1\). We just need to compute \(l\) and \(r\) in advance.

Now let's consider all \(n\) rows (not columns). First, count all rows that are already white lines before clicking. Then we count the number of white rows when the cell \((1,1)\) is clicked, by applying the above method to all rows from \(1\) to \(k\). Ignore the already-white rows that we counted before. So far we obtained the number of white rows when the cell \((1,1)\) is clicked. From now, we slide the window. Add the \(k+1^{th}\) row and remove the \(1^{st}\) row by applying the same method to them, and we obtain the number of white rows when the cell \((2,1)\) is clicked. We can repeat this until we calculate all \(n−k+1\) cases for clicking the cells at the \(1^{st}\) column. Then we repeat the whole process for all \(n−k+1\) columns.

The same process can be done for counting white columns, too. Now we know the number of white rows and white columns when each cell is clicked, so we can find the maximum value among their sums.

Time complexity: \(O(n^2)\)

COdeForce%20round%20578%20Div%202%20D.png?raw=true

配上图,一开始我也是这么想的,但是想出来是个\(O(n^2k)\)的假算法,T在第12个点,后来看了题解发现其实可以预处理一下,计算橡皮擦擦\((i,j)\)\((i+k-1,j+k-1)\)这个大正方形对行列的贡献的时候可以优化到\(O(n^2)\),不需要每次都重复计算K行K列。

The Code Of My Program

/*********************
*@Author:   ChenShou *
*@Language: C++11    *
*********************/
//#include <bits/stdc++.h> 
#pragma comment(linker, "/STACK:102400000,102400000")
#include<functional>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<sstream> 
#include<iomanip>
#include<numeric>
#include<cctype>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<deque>
#include<stack>
#include<cmath>
#include<list>
#include<map>
#include<set>

//#define DEBUG
#define RI register int
#define endl "\n"

using namespace std;
typedef long long ll;
//typedef __int128 lll;
//const int N=100000+10;
const int M=100000+10;
const int MOD=1e9+7;
const double PI = acos(-1.0);
const double EXP = 1E-9;
const int INF = 0x3f3f3f3f;

inline ll read(){
    long long x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f; 
}

ll n,k;
int mp[2005][2005]={0};
char paint[2005];
    int add_r[2005][2005]={0},add_c[2005][2005]={0};

int main()
{
#ifdef DEBUG
    freopen("input.in", "r", stdin);
    //freopen("output.out", "w", stdout);
#endif
    //cout.tie(0);
    //ll t ; 
    //scanf("%lld",&t);
    //while(t--){
    //}
    n=read(),k=read();
    for(int i= 1 ;i<=n ; i++){
        scanf("%s",paint+1);
        int mmin=-1,mmax=-1;
        for(int j=1;j<=n;j++){
             mp[i][j]=(paint[j]=='W'?0:1);//   W  0   //   B  1   
             
             if(mp[i][j]){
                if(mmin==-1)mmin=j;
                mmax=j;
             }
             
        }
        mp[i][n+1]=mmin,mp[i][n+2]=mmax;
    }
    
    for(int j= 1 ;j<=n ; j++){
        int mmin=-1,mmax=-1;
        for(int i=1;i<=n;i++){
             if(mp[i][j]){
                if(mmin==-1)mmin=i;
                mmax=i;
             }
        }
        mp[n+1][j]=mmin,mp[n+2][j]=mmax;
    }
    
    
    for(int i=1;i+k-1<=n;i++){
        for(int j=1;j+k-1<=n;j++){
            if(j==1)
                for(int cc=j;cc<=j+k-1;cc++){
                    if(mp[n+1][cc]!=-1&&i<=mp[n+1][cc]&&i+k-1>=mp[n+2][cc])
                        add_c[i][j]++;
                }
            else {
                int tem=0;
                if(mp[n+1][j-1]!=-1&&i<=mp[n+1][j-1]&&i+k-1>=mp[n+2][j-1])tem--;
                if(mp[n+1][j+k-1]!=-1&&i<=mp[n+1][j+k-1]&&i+k-1>=mp[n+2][j+k-1])tem++;
                    add_c[i][j]=add_c[i][j-1]+tem;
            }
        }
    }
    for(int j=1;j+k-1<=n;j++){
        for(int i=1;i+k-1<=n;i++){
            if(i==1)
                for(int rr=i;rr<=i+k-1;rr++){
                    if(mp[rr][n+1]!=-1&&j<=mp[rr][n+1]&&j+k-1>=mp[rr][n+2])
                        add_r[i][j]++;
                }
            else {
                int tem=0;
                if(mp[i-1][n+1]!=-1&&j<=mp[i-1][n+1]&&j+k-1>=mp[i-1][n+2])tem--;
                if(mp[i+k-1][n+1]!=-1&&j<=mp[i+k-1][n+1]&&j+k-1>=mp[i+k-1][n+2])tem++;
                    add_r[i][j]=add_r[i-1][j]+tem;
            }
        }
    }
    int sum=0;
    for(int i=1;i<=n;i++){
        if(mp[i][n+1]==-1)sum++;
        if(mp[n+1][i]==-1)sum++;
    }
    
    int maxx=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            maxx=max(sum+add_c[i][j]+add_r[i][j],maxx);
        }
    }
    printf("%d",maxx);
#ifdef DEBUG
    printf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC);
#endif
    //cout << "Fuck You !" << endl;
    return 0;
}

转载于:https://www.cnblogs.com/--ChenShou--/p/11356071.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值