(初中OJ)2242. 【2017.11.25普及组模拟】Bob
2017-11-29 20:23
204 查看
好吧,我知道我很久没单独写题解了。
这块土地的形状就像一个矩形,长N米,宽M米。我们将它看作是由N×M个小正方形组成。(见图) Bob的房子的形状也是矩形的,其边和土地的边是平行的,而且其顶点与某个小正方形的顶点重合。为了使房子保持平衡,Bob要选具有相同高度的小方格建造房子。
(土地被分成多个小方格。房屋的两个可能建造的位置如右图有红色和蓝色。)
请计算Bob建造房子的方案数。
接下来的N行,每行包含M个整数A[i][j],表示该方格的土地高度。
5 3
2 2 2
2 2 1
1 1 1
2 1 2
1 2 1
【输入样例2】
4 3
1 1 1
1 1 1
2 2 2
2 2 2
27
【输出样例2】
36
对于30%的数据: 1≤N,M≤500;1≤A[i][j]≤10,000;
对于100%的数据:1≤N,M≤1,000;1≤A[i][j]≤1,000,000,000;
对于每一位,维护up[i,j]表示这一列从上开始,有几个连续的与本位相同的数(持续至本位,包括本身,即初值为1)。那么对于一行的up[i]来说,我们再开一个栈来维护从前到目前连续的区间内,相应的矩形个数,举个例子:
额,有点丑,将就着看。
那么假设这些都是同一颜色的,我们做到3、5、9、12、16这一行,1、6号方块是没用的,那么我们可以直接删去,即最终处理出来的栈为2,2,3,3,4。
接着我们要压栈,大概就是将它压成
原数 个数
2 2
3 2
4 1
记得当颜色不一样时整个栈清零。
每次做一位统计一位。
Description
不但奶牛想建造房子,作为一名建筑师的Bob也想建造自己的房子。他买了块土地,问题是土地的地形不平整。这块土地的形状就像一个矩形,长N米,宽M米。我们将它看作是由N×M个小正方形组成。(见图) Bob的房子的形状也是矩形的,其边和土地的边是平行的,而且其顶点与某个小正方形的顶点重合。为了使房子保持平衡,Bob要选具有相同高度的小方格建造房子。
(土地被分成多个小方格。房屋的两个可能建造的位置如右图有红色和蓝色。)
请计算Bob建造房子的方案数。
Input
第 1 行输入包含N和M;接下来的N行,每行包含M个整数A[i][j],表示该方格的土地高度。
Output
输出共一行一个整数,即任务中所需的答案。Sample Input
【输入样例1】5 3
2 2 2
2 2 1
1 1 1
2 1 2
1 2 1
【输入样例2】
4 3
1 1 1
1 1 1
2 2 2
2 2 2
Sample Output
【输出样例1】27
【输出样例2】
36
Data Constraint
对于10%的数据: 1≤N,M≤50;1≤A[i][j]≤10;对于30%的数据: 1≤N,M≤500;1≤A[i][j]≤10,000;
对于100%的数据:1≤N,M≤1,000;1≤A[i][j]≤1,000,000,000;
题解
听说正解是什么单调栈,只是吓人的,其实很简单。对于每一位,维护up[i,j]表示这一列从上开始,有几个连续的与本位相同的数(持续至本位,包括本身,即初值为1)。那么对于一行的up[i]来说,我们再开一个栈来维护从前到目前连续的区间内,相应的矩形个数,举个例子:
额,有点丑,将就着看。
那么假设这些都是同一颜色的,我们做到3、5、9、12、16这一行,1、6号方块是没用的,那么我们可以直接删去,即最终处理出来的栈为2,2,3,3,4。
接着我们要压栈,大概就是将它压成
原数 个数
2 2
3 2
4 1
记得当颜色不一样时整个栈清零。
每次做一位统计一位。
var n,m,i,j,k,tot:longint; ans,jl:int64; up,a:array[0..1000,0..1000]of longint; z:array[0..1000,1..2]of longint; begin readln(n,m); for i:=1 to n do begin for j:=1 to m do begin read(a[i,j]); up[i,j]:=1; if a[i,j]=a[i-1,j] then inc(up[i,j],up[i-1,j]); if j=1 then begin fillchar(z,sizeof(z),0); tot:=1; z[tot,1]:=up[i,j]; z[tot,2]:=1; inc(ans,up[i,j]); continue; end; if a[i,j]<>a[i,j-1] then begin fillchar(z,sizeof(z),0); tot:=1; z[tot,1]:=up[i,j]; z[tot,2]:=1; inc(ans,up[i,j]); continue; end; if up[i,j]<z[tot,1] then begin jl:=1; for k:=tot downto 1 do begin if up[i,j]>=z[k,1] then break; inc(jl,z[k,2]); end; if up[i,j]<z[1,1] then begin tot:=1; z[tot,1]:=up[i,j]; z[tot,2]:=jl; end else begin if up[i,j]=z[k,1] then begin tot:=k; inc(z[tot,2],jl); end else begin tot:=k+1; 4000 z[tot,1]:=up[i,j]; z[tot,2]:=jl; end; end; for k:=1 to tot do inc(ans,z[k,1]*z[k,2]); continue; end; if up[i,j]=z[tot,1] then inc(z[tot,2]) else begin inc(tot); z[tot,1]:=up[i,j]; z[tot,2]:=1; end; for k:=1 to tot do inc(ans,z[k,1]*z[k,2]); end; readln; end; writeln(ans); end.
相关文章推荐
- > 2242. 【2017.11.25普及组模拟】Bob
- 【2017.11.25普及组模拟】Bob
- 2016.11.13【初中部 NOIP普及组 】模拟赛
- 2016.08.18【初中部 NOIP普及组 】模拟赛
- 2016.08.19 初中部 NOIP普及组 模拟赛
- 2016.5.28【初中部 NOIP普及组 】模拟赛
- 2016.10.05【初中部 NOIP普及组 】模拟赛&Aug~Sep总结
- 2016.5.28【初中部 NOIP普及组 】模拟赛
- 2016.08.18【初中部 NOIP普及组 】模拟赛题解
- 初中OJ2105【NOIP2016普及组复赛】魔法阵
- 2016.09.10 初中部 NOIP普及组 模拟赛
- 2016.08.18【初中部 NOIP普及组 】模拟赛
- 2016.10.05【初中部 NOIP普及组 】模拟赛
- 2016.08.19上午【初中部 NOIP普及组 】模拟赛题目
- 2016.09.10【初中部 NOIP普及组 】模拟赛题解
- 2016.10.05【初中部 NOIP普及组 】模拟赛
- 2016.08.19【初中部 NOIP普及组 】模拟赛题解
- 2016.08.19上午【初中部 NOIP普及组 】模拟赛题解
- 2016.5.28【初中部 NOIP普及组 】模拟赛
- 2016.08.18【初中部 NOIP普及组 】模拟赛题解