HDU 4331 Image Recognition

HDU 4331 Image Recognition

本题题目大意在一个01方阵中找出四条边全都是1的正方形的个数,对于正方形内部则没有要求。

一个直观的想法是首先用N^2的时间预处理出每一个是1的点向上下左右四个方向能够延伸的1的最大长度,记为四个数组l, r, u, d。然后我们观察到正方形有一个特征是同一对角线上的两个顶点在原方阵的同一条对角线上。于是我们可以想到枚举原来方阵的每条对角线,然后我们对于每条对角线枚举对角线上所有是1的点i,那么我们可以发现可能和i构成正方形的点应该在该对角线的 [i, i + min(r[i], d[i]) – 1] 闭区间内, 而在这个区间内的点 j 只要满足 j – i + 1 <= min(l[j], u[j]) 也就是满足j – min(l[j], u[j]) + 1 <= i,这样的 (i, j) 就能构成一个正方形。也就是说对于每条对角线,我们可以构造一个数组 a, 使得a[i] = i – min(l[i], u[i]) + 1

然后对这个数组有若干次查询,每次查询的是区间 [i, i + min(r[i], d[i]) – 1]内有多少个数满足 a[j] <= i,所有这些问题答案的和就是该问题的结果。对于这个问题,我们可以通过离线算法,先保存所有查询的区间端点,并对所有端点排序。然后使用扫描线算法,如果扫描到的是第i次查询的左端点,就让当前结果减去当前扫描过的数中 <= i的个数,如果扫描到的是第i次查询的有短点,则让当前结果加上当前扫描过的数中 <= i的个数,最后所有结果相加即可。

维护当前数出现的个数可以使用树状数组。这样对于每条对角线求结果的复杂度为O(nlogn),算法总的复杂度为O(n^2logn)。

HDU 4331 Image Recognition
HDU 4331 Image Recognition
View Code

View Code 
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<cstring>
#include<vector>
#include<string>
#define LL long long
using namespace std;
int map[1024][1024],l[1024][1024],u[1024][1024],d[1024][1024],r[1024][1024],a[2024],c[2024];
class Node{
public:
      bool left;
      int x,id;    
}p[2024];
bool cmp( Node a, Node b ){
    if( a.x == b.x ) return a.left;
    return a.x < b.x;    
}
int lowbit( int x ){
    return x&(-x);    
}
void Updata( int x, int n ){
    for( int i = x ; i <= n ; i += lowbit(i) )
          c[i] ++;    
}
int Query( int x ){
    int ans = 0;
    for( int i = x; i > 0 ; i -= lowbit(i) )
         ans += c[i];
    return ans;    
}
int res( int n, int m ){
    int ans = 0;
    memset( c , 0 , sizeof( c ) );
    sort( p , p + m , cmp );
    for( int i = 0 ; i < m ; i ++ )
         if( p[i].left ) {
                ans -= Query( p[i].id );
                Updata( a[p[i].x] ,n );
         }
         else ans +=Query( p[i].id );
//    printf( "__%d\n",ans );
    return ans;
}
int Solve( int n )
{
    int ans=0;
    for( int i =1 ; i <= n ; i ++ ){
        int m = 0;
        for( int j = 1 ; j <= i ; j ++ ){
                int x=n-i+j,y=j;         
                if( map[x][y] == 1 ){
                    a[y] = y - min( l[x][y],u[x][y] ) + 1;
                    p[m].left = true;p[m].id=y;p[m].x=y,p[m].id=y;
                    m++;
                    p[m].left=false;p[m].x=y+min( r[x][y],d[x][y] )-1;p[m].id=y;
                    m++;
                    }        
            }   
        ans += res( n ,m ); 
//        printf( "ans=%d\n",ans );   
      }    
      for( int i =2 ; i <= n ; i ++ ){
        int m = 0;
        for( int j = 1 ; j <= n - i + 1 ; j ++ ){
                  int x=j,y=i+j-1;             
                if( map[x][y] == 1 ){
                    a[y] = y - min( l[x][y],u[x][y] ) + 1;
                    p[m].left = true;p[m].id=y;p[m].x=y;
                    m++;
                    p[m].left=false;p[m].x=y+min( r[x][y],d[x][y] )-1;p[m].id=y;
                    m++;
                    }        
            }  
        ans += res( n ,m );   
//        printf( "ans=%d\n",ans ); 
      }    
      return ans;
}
int main(  ){
    int T,n;
    while( scanf( "%d",&T )==1 ){
        for( int cas = 1 ; cas <= T ;cas++ ){
            memset( u , 0 , sizeof( u ) );
            memset( d , 0 , sizeof( d ) );
            memset( l , 0 , sizeof( l ) );
            memset( r , 0 , sizeof( r ) );
             scanf( "%d",&n );
             LL cnt = 0,ans=0;
             for( int i = 1 ; i <= n ; i ++ )
                  for( int j = 1; j <= n ; j ++ ){
                       scanf( "%d",&map[i][j] ); 
                       if( map[i][j] == 0 ) u[i][j] = l[i][j] = 0;
                      else{
                        u[i][j] = u[i-1][j]  + 1;
                        l[i][j] = l[i][j-1] + 1;
                     }
                  }
            for( int i = n ; i >0  ; i -- ){
                 for( int j = n ;j > 0 ; j -- ){
                        if( map[i][j] == 0 ) d[i][j] = r[i][j] = 0;
                        else{
                        d[i][j] = d[i+1][j] + 1;
                        r[i][j] = r[i][j+1] + 1;
                       }
                     }
                }
            printf( "Case %d: %d\n",cas,Solve( n ) );
       }
   }
    //system( "pause" );
    return 0;
}

 

 

转载于:https://www.cnblogs.com/bo-tao/archive/2012/08/03/2622211.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/110357.html原文链接:https://javaforall.net

(0)
上一篇 2021年8月19日 上午10:00
下一篇 2021年8月19日 上午10:00


相关推荐

  • Button和ImageButton[通俗易懂]

    Button和ImageButton

    2022年1月30日
    208
  • pycharm和anaconda区别_python init

    pycharm和anaconda区别_python initIcurrentlyhavePycharm5.0.4rightnowandmyteacherwantsmetochangetoAnaconda.DodifferentGUIsactuallyaffectyourprogramming?WhatarelibrariesandwhatcausesoneGUItobemoreadvanced…

    2022年8月25日
    12
  • 海思hi3798mv300和310的区别_海思3516

    海思hi3798mv300和310的区别_海思3516在网上搜寻海思HI3519或者hi3516实时识别除了官方给的SDK中有Rfcn的实时识别例子之外,其它都是读图片例子。官方例子中给了如下网络参考:Rfcn、Segnet、FasterRcnn、Cnn、Ssd、Yolov1、Yolov2、Yolov3、Lstm、Pvanet在SDK中文件夹路径为/rp-hi3516dv300-busybox/smp/a7_linux/mpp/sample/svp/nnie其中有一个sample_nnie_main.c文件,官方例子如下:/************

    2026年2月20日
    3
  • 表白生成器PHP源码,表白网页在线生成源码[通俗易懂]

    表白生成器PHP源码,表白网页在线生成源码[通俗易懂]在520这个节日里面,很多人都开始了表白计划,对于那些不敢说出口的问题,就直接来此下载520表白网页一键生成软件,帮助你们直接生成最棒的表白页面,让你们增加成功的机会。520表白网页一键生成软件简介如果你喜欢她不能亲自向她说不如做个网页,把自己想说的话写进去,然后发个地址给她,里面添加她喜欢的音乐或者mv。不会做网页怎么办,没事。表白网页生成器帮助你!无需任何编程。一键生成,然后把生成在桌面的i…

    2022年5月21日
    37
  • microsoft edge无法连接到代理服务器(ie代理服务器错误)

    电脑里有谷歌浏览器也有系统自带的Microsoftedge浏览器,谷歌浏览器可以上网,edge不能上网,出现无法连接到代理服务器的字样。解决方法:方法1、直接根据当前浏览器页面中的“打开代理设置”,(应该是叫这个名字),直接跳到代理界面,把“自动检测设置”按钮打开。重启浏览器。就OK了。 方法2、打开浏览器的设置按钮,在最后一行找到“设置”,点进去后,找到“高级设置”,点击“查看高级设置”,在找…

    2022年4月11日
    683
  • linux文件名乱码删除,linux下删除文件名乱码文件

    linux文件名乱码删除,linux下删除文件名乱码文件linux 下通过 rm 命令来删除文件 但是如果要删除文件名乱码的文件 就不能直接使用 rm 命令了 因为压根就无法输出文件名来 不过借助 find 命令可以实现对其删除 在 linux 下对于每个文件都一个对应的不变的 inode 号 使用 ls li 可以查看到文件的 inode 号 同时 find 可以根据 inode 号来查找 另外 find 命令中可以执行其他的命令 删除的步骤如下 通过 ls li 获取要删除乱码文件名

    2026年3月26日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号