zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    使用AntDesignBlazor的Notification等组件
    Blazor入门笔记(6)-组件间通信
    Blazor入门笔记(5)-数据绑定
    Blazor入门笔记(4)-组件的生命周期
    Blazor入门笔记(3)-C#与JS交互
    Blazor入门笔记(2)-分部类组件与组件的继承
    Blazor入门笔记(1)-从0构建一个组件
    添加右键上下文菜单后,点击后需要获取到源控件
    NPOI,给指定的excle创建个下拉框验证
    有的时候,给指定的控件,追加一个装饰器Adorner,备注下
  • 原文地址:https://www.cnblogs.com/--ChenShou--/p/11356071.html
Copyright © 2011-2022 走看看