• 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))

    配上图,一开始我也是这么想的,但是想出来是个(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 "
    "
    
    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
    ",(double)clock()/CLOCKS_PER_SEC);
    #endif
        //cout << "Fuck You !" << endl;
        return 0;
    }
    
  • 相关阅读:
    file_zilla 通过key连接远程服务器
    git 恢复丢失的文件
    花括号中的json数据--->转为数组array
    3种日志类型,微信付款反馈-->写入txt日志
    清空数据库中所有表--连表删除
    冒泡排序, 使用最低票价.---双重循环,一重移动次数.二重移动
    navicat 连接远程mysql
    付款前.检查状态.防止重复付款,需要ajax设置为同步,等待ajax返回结果再使用
    反射
    设计模式六大原则
  • 原文地址:https://www.cnblogs.com/--ChenShou--/p/11356071.html
Copyright © 2020-2023  润新知