• CodeForces


    题目链接

    先dp求出以每个红色区域右下角为中心的能成为logo的最大半径

    然后二维RMQ预处理,之后可O(1)询问任意子矩形中的最大值

    最后对于每个询问二分最大logo的半径mid,这样问题就转化成判定是否存在半径大于等于mid的logo,在(x1+mid-1,y1+mid-1,x2-mid,y2-mid)的范围内找最大值判断是否大于等于mid即可

    复杂度$O(nmlognlogm+qlog(min(n,m)))$

    第一次写二维RMQ,感觉有点类似于树套树,代码量略小于树套树,但容易写挫

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=500+10,mod=1e9+7,inf=0x3f3f3f3f;
     5 int n,m,Q,a[N][N],b[N][N],c[N][N],d[4][N][N],r[N][N],ST[N][12][N][12],Log[N];
     6 char s[N][N];
     7 void buildy(int i,int k) {
     8     for(int j=1; j<=m; ++j)
     9         ST[i][k][j][0]=k==0?r[i][j]:max(ST[i][k-1][j][0],ST[i+(1<<(k-1))][k-1][j][0]);
    10     for(int l=1; l<=Log[m]; ++l)
    11         for(int j=1; j+(1<<l)-1<=m; ++j)
    12             ST[i][k][j][l]=max(ST[i][k][j][l-1],ST[i][k][j+(1<<(l-1))][l-1]);
    13 }
    14 void build() {
    15     for(int i=1; i<=n; ++i)buildy(i,0);
    16     for(int k=1; k<=Log[n]; ++k)
    17         for(int i=1; i+(1<<k)-1<=n; ++i)buildy(i,k);
    18 }
    19 int qry(int x1,int y1,int x2,int y2) {
    20     int k=Log[x2-x1+1],l=Log[y2-y1+1];
    21     return max(max(ST[x1][k][y1][l],ST[x1][k][y2-(1<<l)+1][l]),max(ST[x2-(1<<k)+1][k][y1][l],ST[x2-(1<<k)+1][k][y2-(1<<l)+1][l]));
    22 }
    23 int qry2(int x1,int y1,int x2,int y2) {
    24     int ret=0;
    25     int l=1,r=min((x2-x1+1)/2,(y2-y1+1)/2);
    26     while(l<=r) {
    27         int mid=(l+r)>>1;
    28         if(qry(x1+mid-1,y1+mid-1,x2-mid,y2-mid)>=mid)ret=mid,l=mid+1;
    29         else r=mid-1;
    30     }
    31     return ret*ret*4;
    32 }
    33 int main() {
    34     Log[0]=-1;
    35     for(int i=1; i<N; ++i)Log[i]=Log[i>>1]+1;
    36     scanf("%d%d%d",&n,&m,&Q);
    37     for(int i=1; i<=n; ++i)scanf("%s",s[i]+1);
    38     for(int i=1; i<=n; ++i)
    39         for(int j=1; j<=m; ++j) {
    40             a[i][j]=(s[i][j]=='R');
    41             b[i][j]=(a[i][j]?b[i-1][j]+1:0);
    42             c[i][j]=(a[i][j]?c[i][j-1]+1:0);
    43             d[0][i][j]=min(min(b[i][j],c[i][j]),d[0][i-1][j-1]+1);
    44         }
    45     for(int i=1; i<=n; ++i)
    46         for(int j=m; j>=1; --j) {
    47             a[i][j]=(s[i][j]=='G');
    48             b[i][j]=(a[i][j]?b[i-1][j]+1:0);
    49             c[i][j]=(a[i][j]?c[i][j+1]+1:0);
    50             d[1][i][j]=min(min(b[i][j],c[i][j]),d[1][i-1][j+1]+1);
    51         }
    52     for(int i=n; i>=1; --i)
    53         for(int j=1; j<=m; ++j) {
    54             a[i][j]=(s[i][j]=='Y');
    55             b[i][j]=(a[i][j]?b[i+1][j]+1:0);
    56             c[i][j]=(a[i][j]?c[i][j-1]+1:0);
    57             d[2][i][j]=min(min(b[i][j],c[i][j]),d[2][i+1][j-1]+1);
    58         }
    59     for(int i=n; i>=1; --i)
    60         for(int j=m; j>=1; --j) {
    61             a[i][j]=(s[i][j]=='B');
    62             b[i][j]=(a[i][j]?b[i+1][j]+1:0);
    63             c[i][j]=(a[i][j]?c[i][j+1]+1:0);
    64             d[3][i][j]=min(min(b[i][j],c[i][j]),d[3][i+1][j+1]+1);
    65         }
    66     for(int i=1; i<=n; ++i)
    67         for(int j=1; j<=m; ++j)
    68             r[i][j]=min(min(d[0][i][j],d[1][i][j+1]),min(d[2][i+1][j],d[3][i+1][j+1]));
    69     build();
    70     while(Q--) {
    71         int x1,y1,x2,y2;
    72         scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    73         printf("%d
    ",qry2(x1,y1,x2,y2));
    74     }
    75     return 0;
    76 }
  • 相关阅读:
    epoll精髓【epoll】
    linux下调试core的命令,察看堆栈状态命令 摘录(http://blog.csdn.net/yearn520/article/details/6663265)
    使用epoll 在 linux 上开发高性能应用服务器【epoll】
    linux下epoll如何实现高效处理百万句柄的[转]【epoll】
    log4cplus入门
    非阻塞式服务器和客户端程序(TCP)【简单的原理例子】
    Linux有用的命令记录
    在Linux上的使用开源C++日志库log4cplus
    静态库和动态库的区别
    localtime多线下不安全,localtime_r线程安全
  • 原文地址:https://www.cnblogs.com/asdfsag/p/12386306.html
Copyright © 2020-2023  润新知