您的位置:首页 > 其它

【JZOJ3633】【汕头市选2014】数数(count) (栈)

2018-02-01 08:00 260 查看

Problem

  N行M列的矩形上有K个宝藏。统计包含至少1个宝藏的子矩形数量。

Hint

对于20% 的数据,N,M <= 50;

对于50% 的数据,N,M <= 1000;

对于80% 的数据,N <=1000;M <= 10^9;

对于100% 的数据,1 <= N,M <= 10^9; 1 <= K <= 1000; 1 <= Xi <= N,1 <= Yi <= M。

Solution

20points

  不用说了吧,无脑暴力——滥用时间,枚举矩阵左上角和右下角。

  时间复杂度:O(n2m2)O(n2m2)。

50points

  题目要求我们求至少包含1个宝藏的子矩阵数量,我们要有逆向思维,可以先求出不含任何宝藏的子矩阵数量,然后用总方案数减去它。

  至于不含任何宝藏的子矩阵数量,我们可以先把有宝藏的地方打个标记,然后设up[i][j]表示点(i,j)上方的第一个有宝藏的格子(包括它自己)的行。那么我们可以在O(nm)O(nm)的时间内预处理出它来。

  我们先枚举一个i,表示子矩阵的下边界;然后再枚举一个j,表示子矩阵的右边界。然后我们在扫j的时候,顺便维护一个单调递减的单调栈stack,贮存我们经过的点的up。比如说,有一个3*3的矩阵如下图所示:



  若红色区域为宝藏,黄色区域为我们当前做到的点,则此时stack={2,1}。如果再往后一格,stack中的所有元素就会被先后踢出栈,另加上一个2。

  我们可以维护栈中每一个元素所占的宽度,那么可以很方便地更新答案。

  时间复杂度:O(nm)O(nm)。

100points

  50points的做法硬伤就在于难以解决图太大的局
4000
面。但我们注意到此题有一个很大的图,但图中却有相对很少的、有宝藏的点。

  来一波套路:离散化

  但是我们注意到,离散化以后,原本间隔很多行的两点可能会紧挨着,如下图所示:



  这样一来,我们便没有计算到x,y之间的空隙对答案的贡献。于是,考虑将两点间的空行留一行,也就是说,上图应该会变成这样:



  类似的,大矩阵的边界到某个点之间的空行,也留出一行。

  考虑记录离散化后每一个行、每一列表示的原图的行数、列数。譬如上图中x到y的空行则记录为3,空列也记录为3;而x所占的那一行,记录为1,列也肯定记录为1(因为一个宝藏肯定只能待在一个1*1的矩阵里)。

  然后仿照50points,枚举i、j,维护单调栈,但是要注意此时的行、列可能都不单单只是一行、一列。

  时间复杂度:O(k2)O(k2)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: