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

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 ( n 2 m 2 )

50points

  题目要求我们求至少包含1个宝藏的子矩阵数量,我们要有逆向思维,可以先求出不含任何宝藏的子矩阵数量,然后用总方案数减去它。
  至于不含任何宝藏的子矩阵数量,我们可以先把有宝藏的地方打个标记,然后设up[i][j]表示点(i,j)上方的第一个有宝藏的格子(包括它自己)的行。那么我们可以在 O(nm) O ( n m ) 的时间内预处理出它来。
  我们先枚举一个i,表示子矩阵的下边界;然后再枚举一个j,表示子矩阵的右边界。然后我们在扫j的时候,顺便维护一个单调递减的单调栈stack,贮存我们经过的点的up。比如说,有一个3*3的矩阵如下图所示:
这里写图片描述
  若红色区域为宝藏,黄色区域为我们当前做到的点,则此时stack={2,1}。如果再往后一格,stack中的所有元素就会被先后踢出栈,另加上一个2。
  我们可以维护栈中每一个元素所占的宽度,那么可以很方便地更新答案。
  时间复杂度: O(nm) O ( n m )

100points

  50points的做法硬伤就在于难以解决图太大的局面。但我们注意到此题有一个很大的图,但图中却有相对很少的、有宝藏的点。
  来一波套路:离散化
  但是我们注意到,离散化以后,原本间隔很多行的两点可能会紧挨着,如下图所示:
这里写图片描述
  这样一来,我们便没有计算到x,y之间的空隙对答案的贡献。于是,考虑将两点间的空行留一行,也就是说,上图应该会变成这样:
这里写图片描述
  类似的,大矩阵的边界到某个点之间的空行,也留出一行。
  考虑记录离散化后每一个行、每一列表示的原图的行数、列数。譬如上图中x到y的空行则记录为3,空列也记录为3;而x所占的那一行,记录为1,列也肯定记录为1(因为一个宝藏肯定只能待在一个1*1的矩阵里)。
  然后仿照50points,枚举i、j,维护单调栈,但是要注意此时的行、列可能都不单单只是一行、一列。
  时间复杂度: O(k2) O ( k 2 )

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值