> 2242. 【2017.11.25普及组模拟】Bob

  1. 【2017.11.25普及组模拟】Bob
    (File IO): input:bob.in output:bob.out
    时间限制: 1000 ms 空间限制: 262144 KB 具体限制

题目描述

不但奶牛想建造房子,作为一名建筑师的Bob也想建造自己的房子。他买了块土地,问题是土地的地形不平整。
这块土地的形状就像一个矩形,长N米,宽M米。我们将它看作是由N×M个小正方形组成。(见图) Bob的房子的形状也是矩形的,其边和土地的边是平行的,而且其顶点与某个小正方形的顶点重合。为了使房子保持平衡,Bob要选具有相同高度的小方格建造房子。
(土地被分成多个小方格。房屋的两个可能建造的位置如右图有红色和蓝色。)
请计算Bob建造房子的方案数。

输入

第 1 行输入包含N和M;
接下来的N行,每行包含M个整数A[i][j],表示该方格的土地高度。

输出

输出共一行一个整数,即任务中所需的答案。

样例输入

【输入样例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

样例输出

【输出样例1】
27

【输出样例2】
36

数据范围限制

对于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;

比赛0分。

10分水法:四重循环,四重循环,50^4,能过。

那么,给n,m<=500(n^3)和n,m<=1000(n^2)有什么用?

设f[i,j]为以i,j为右下角所有答案矩阵的数量。

答案为所有f[i,j]相加。时间复杂度:O(n^2)

那么怎么求呢?

设up[i,j]为i,j上连续有几个,O(n^2)

画一幅图:维护单调栈]![看下图

f[i,j]等于栈里面所有数之和

更新i时栈清空

至此完结。

代码(请勿抄袭)

pascal代码:

var
        i,j:longint;
        k,m,n,o,p,l,s,t,r,ans:int64; 
        a,up,f:array[0..1000,0..1000] of int64;
        zhan:array[0..10000000] of int64;
begin
        assign(input,'bob.in');reset(input);
        assign(output,'bob.out');rewrite(output);
        readln(n,m);
        for i:=1 to n do begin
                for j:=1 to m do
                        read(a[i,j]);
                readln;
        end;
        for i:=1 to n do begin
                for j:=1 to m do begin
                        if a[i-1,j]=a[i,j] then up[i,j]:=up[i-1,j]+1 else up[i,j]:=1;
                end;
        end;
        for i:=1 to n do begin
                zhan[0]:=0;
                ans:=0;
                for j:=1 to m do begin
                        if (j=1) or (a[i,j]=a[i,j-1]) then begin
                                inc(zhan[0]);
                                zhan[zhan[0]]:=up[i,j]; inc(ans,up[i,j]);
                                k:=zhan[0];
                                while (zhan[k]<zhan[k-1]) do begin
                                        dec(ans,zhan[k-1]-zhan[k]);
                                        zhan[k-1]:=zhan[k];
                                        dec(k);
                                        if k=1 then break;
                                end;
                        end else begin
                                zhan[0]:=1;
                                zhan[1]:=up[i,j];
                                ans:=up[i,j];
                        end;
                        f[i,j]:=ans;
                end;
        end;
        for i:=1 to n do
                for j:=1 to m do
                        inc(s,f[i,j]);
        writeln(s);
        close(input);close(output);
end.

猜你喜欢

转载自blog.csdn.net/wangyuda123456789/article/details/78676189