• Codeforces 1262E Arson In Berland Forest(二维前缀和+二维差分+二分)


     题意是需要求最大的扩散时间,最后输出的是一开始的火源点,那么我们比较容易想到的是二分找最大值,但是我们在这满足这样的点的时候可以发现,在当前扩散时间k下,以这个点为中心的(2k+1)2的正方形块内必须全部都是'X'才行,那么要访问这样的块内的'X'个数显然需要使用二维前缀和维护一下就可以O(1)求出个数,那么这部分问题我们解决,接下来就是二分的如何Check,那么既然我们之前找到了这样满足当期扩散时间的点后,我们只需要直接将这块矩形内部的点全部打标记,显然我们可以得知,如果当前扩散时间是满足要求的,那么所有的'X'最后都会被打上标记,那么我们可以利用这一性质,对满足这样的矩形进行二维差分,最后O(n*m)把标记推掉,在check一遍所有被打伤标记的点是不是等于等于一开始'X'的个数,若等于,那么我们可以将区间移至右边,否则移至左边。

    最后记得不要用cin,cout,T的死去活来.....

     1 //      ——By DD_BOND 
     2  
     3 #include<bits/stdc++.h>
     4  
     5 using namespace std;
     6  
     7 typedef long long ll;
     8 
     9 const int MAXN=1e6+10;
    10  
    11 inline ll sqr(ll x){ return x*x; }
    12  
    13 char s[MAXN];
    14  
    15 int main(void)
    16 {
    17     int n,m;    scanf("%d%d",&n,&m);
    18     vector<vector<int> >ok (n+2,vector<int>(m+2));
    19     vector<vector<int> >sum(n+2,vector<int>(m+2));
    20     vector<vector<int> >tmp(n+2,vector<int>(m+2));
    21     for(int i=1;i<=n;i++){
    22         scanf("%s",s+1);
    23         for(int j=1;j<=m;j++)    if(s[j]=='X')   sum[i][j]=1;
    24     }
    25     for(int i=1;i<=n;i++)
    26         for(int j=1;j<=m;j++)
    27             sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
    28     int l=0,r=(min(n,m)-1)/2,res=0;
    29     while(l<=r){
    30         int mid=(l+r)>>1;
    31         for(int i=1;i<=n;i++)
    32             for(int j=1;j<=m;j++)
    33                 tmp[i][j]=0;
    34         for(int i=mid+1;i<=n-mid;i++)
    35             for(int j=mid+1;j<=m-mid;j++)
    36                 if(sum[i+mid][j+mid]-sum[i-mid-1][j+mid]-sum[i+mid][j-mid-1]+sum[i-mid-1][j-mid-1]==sqr(2*mid+1)){
    37                     tmp[i-mid][j-mid]+=1;
    38                     tmp[i-mid][j+mid+1]+=-1;
    39                     tmp[i+mid+1][j-mid]+=-1;
    40                     tmp[i+mid+1][j+mid+1]+=1;
    41                 }
    42         int f=0;
    43         for(int i=1;i<=n;i++)
    44             for(int j=1;j<=m;j++)
    45                 if(tmp[i][j]+=tmp[i-1][j]+tmp[i][j-1]-tmp[i-1][j-1])
    46                     f++;
    47         if(f==sum[n][m])   l=mid+1,res=mid;
    48         else    r=mid-1;
    49     }
    50     printf("%d
    ",res);
    51     for(int i=res+1;i<=n-res;i++)
    52         for(int j=res+1;j<=m-res;j++)
    53             if(sum[i+res][j+res]-sum[i-res-1][j+res]-sum[i+res][j-res-1]+sum[i-res-1][j-res-1]==sqr(2*res+1))
    54                 ok[i][j]=1;
    55     for(int i=1;i<=n;i++){
    56         for(int j=1;j<=m;j++)   putchar((ok[i][j]?'X':'.'));
    57         puts("");
    58     }
    59     return 0;
    60 }
  • 相关阅读:
    动态网络社团检测学习笔记 --- 随机块模型小结之简介
    十五组第四次作业
    17现代软件工程十五组第二次作业
    17现代软件工程十五组第三次作业
    现代软件工程2017十五组成员介绍
    软件测试学习日志3 ————软件测试作业之控制流图
    软件测试学习日志———— round 2 Junit+intellj idea 安装及简单的测试使用
    软件测试学习日志————round 1 some questions of two small programs
    [关于printPrime是()方法的控制流图和点覆盖、边覆盖、主路径覆盖]
    【在myeclipse中使用Junit(4.12), Hamcrest(1.3) 和Eclemma】
  • 原文地址:https://www.cnblogs.com/dd-bond/p/11934531.html
Copyright © 2020-2023  润新知