• [2013腾讯马拉松 3月23日]HDU 4517 小小明系列故事——游戏的烦恼


    腾讯马拉松,我报的是3月23日的那场。其他的几场也看了,不过毕竟其他几日做的是看客,自然也没费劲去思考,23日这场是自己做的,所以比较认真一些。现场AC了3题,分别是A,C,E,做完这3道已经接近1个半小时了,看了提交貌似另外两道很难,无力再去开题了。A题没注意标准时间输出WA了一次,其他1A。由于罚时少,RANK刚好挤进了前50,运气还不错。

    貌似3月25日的题目最难……只要一题就能够出线,一个报了这场的学姐不知是否顺利晋级。

    其中A,E题是水题。A题是计算日期,老生常谈的东西,不说了;E题是典型的流水线模型,稍微一琢磨就能AC。

    至于另外两个题……,B题很直白,因式分解,记得在12年某场网络赛上见过这类题,这种神题小白怎么敢碰呢。D题倒是感觉是一道数位DP?(不是很清楚),先不去搜报告了,等有空自己思考思考。

    这里主要说说C题。题意抽象成模型其实就是求一个大的点阵,被'*'和'.'填充,找满足有多少个x*y的矩阵,使得矩阵内的点全是'*',x*y横放竖放都行。点阵大小2000*2000。

    暴力么的,就不要想了,时间复杂度N的好几次方了。

    说到优化,首先想到2维线段树在时间复杂度上应该勉强能卡过此题,不过线段树要求空间太大,就这个题的数据量而言,此路不通。

    后来想到,这个题所执行的功能仅仅是查询,是一个完全静态的问题,线段树所就有点大材小用了,想到这里貌似找到突破口。

    静态问题,常用的解题策略就是预处理。这个题我想到的方法是把方阵看成01阵,'*'代表1。然后预处理sum[i,j],sum[i,j]代表[1,1]~[i,j]这个矩阵的和。那么很明显

    sum[i,j]=val[i,j]+sum[i,j-1]+sum[i-1,j]-sum[i-1,j-1]。预处理的时间复杂度是O(n*m*1)。

    剩下的工作就是统计了,x*y的矩阵横竖都扫一遍,找到大小为x*y的子阵和为x*y的,结果就+1。

    对于x*y的矩阵来说判断条件是:sum[i][j]-sum[i][j-y]-sum[i-x][j]+sum[i-x][j-y]==x*y

    对于y*x的矩阵来说判断条件是:sum[i][j]-sum[i][j-x]-sum[i-y][j]+sum[i-y][j-x]==x*y

    判定的时间复杂度是O(2*n*m*1)。所以该方法的时间复杂度是O(n*m)。

    这题有个trap,x==y的时候,只统计一次就好。初始化sum的时候最好不要memset,很容易超时,手动写循环。当时用memset,900+MS卡过,吓尿了。

    说到这里貌似就完了。不过我想另外扩展一下。如果这个题需要动态维护矩阵信息,如修改某一点的值,该怎么做?

    修改sum[][]的值显然不现实,复杂度太高。线段树可解,可是内存会爆掉。有没有更好的办法?有的,需要用到位运算的思想,具体的做法这里不详细讲了,有兴趣的可以去查一下资料。

    View Code
     1 #include <map>
     2 #include <set>
     3 #include <list>
     4 #include <queue>
     5 #include <stack>
     6 #include <cmath>
     7 #include <ctime>
     8 #include <vector>
     9 #include <bitset>
    10 #include <cstdio>
    11 #include <string>
    12 #include <numeric>
    13 #include <cstring>
    14 #include <cstdlib>
    15 #include <iostream>
    16 #include <algorithm>
    17 #include <functional>
    18 using namespace std;
    19 typedef long long ll;
    20 #define exp 1e-8
    21 #define inf 0x7fffffff
    22 #define read freopen("in.txt","r",stdin)
    23 #define write freopen("out.txt","w",stdout)
    24 #define maxn 2005
    25 #define maxe maxn*maxn*2
    26 int mp[maxn][maxn];
    27 char ss[maxn];
    28 int main()
    29 {
    30     //read;
    31     int n,m;
    32     while(~scanf("%d%d",&n,&m)&&(n+m))
    33     {
    34         int x,y;
    35         scanf("%d%d",&x,&y);
    36         for(int i=0;i<=n;i++)
    37             for(int j=0;j<=m;j++)mp[i][j]=0;
    38         for(int i=0;i<n;i++)
    39         {
    40             scanf("%s",ss);
    41             for(int j=0;j<m;j++)if(ss[j]=='*')mp[i+1][j+1]=1;
    42         }
    43         for(int i=1;i<=n;i++)
    44             for(int j=1;j<=m;j++)
    45                 mp[i][j]=mp[i][j]+mp[i-1][j]+mp[i][j-1]-mp[i-1][j-1];
    46         int tt=x*y;
    47         ll ans=0;
    48         for(int i=x;i<=n;i++)
    49             for(int j=y;j<=m;j++)
    50                 if(mp[i][j]-mp[i][j-y]-mp[i-x][j]+mp[i-x][j-y]==tt)ans++;
    51         if(x!=y)for(int i=y;i<=n;i++)
    52             for(int j=x;j<=m;j++)
    53                 if(mp[i][j]-mp[i][j-x]-mp[i-y][j]+mp[i-y][j-x]==tt)ans++;
    54         printf("%I64d\n",ans);
    55     }
    56     return 0;
    57 }
  • 相关阅读:
    2018-06-15for与数组/for-in与数组/一维二维多维数组
    2018-06-14控制语句for+switch+while循环
    2018-06-13JS分支结构+转义符
    2018-06-12JavaScript基础知识1
    2018-06-11笔记
    2018-06-08CSS常用样式+浮动+定位+盒子模型
    2018-06-06Div+CSS基础理论
    2018-06-05表单结构
    2018-06-04表格结构+表格嵌套
    2018-06-02笔记
  • 原文地址:https://www.cnblogs.com/mcflurry/p/2982292.html
Copyright © 2020-2023  润新知