广告印刷 题解(单调队列)

题目描述

      最近,afy决定给TOJ印刷广告,广告牌是刷在城市的建筑物上的,城市里有紧靠着的N个建筑。afy决定在上面找一块尽可能大的矩形放置广告牌。我们假设每个建筑物都有一个高度,从左到右给出每个建筑物的高度H1,H2…HN,且0

输入

中的第一行是一个数n (n<= 400,000 )
第二行是n个数,分别表示每个建筑物高度H1,H2…HN,且0

输出

输出文件 ad.out 中一共有一行,表示广告牌的最大面积。

样例输入

6
5 8 4 4 8 4

样例输出

24
 
 
【解释】各个测试点一秒,
但就这道题来说,n<= 400,000,我们如果用枚举不会过全部数据,我们应设计出o(n)的算法来解决,这是单调队列就可以派上用场了。
具体做法是 先正着扫一遍,再倒着扫一遍,找到每一个数的 右极限与 左极限,最后找出最大值。
注意:这个是单调栈的做法,单调队列需要两遍均可弹出。
pascal完整程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
vartemp,ans:int64;
n,p,q,i,j:longint;
a:array[0..400000]of longint;
b,r,l:array[0..400000]of longint;
begin
fillchar(b, sizeof (b),0);
readln(n);
for i:=1 to n do read(a[i]);
p:=1;
q:=0;
for i:=1 to n+1 do begin
while (p<=q) and (a[i] do begin
r[b[q]]:=i;
dec(q);
end;
inc(q);
b[q]:=i;
end;
fillchar(b, sizeof (b),0);
p:=1;
q:=0;
for i:=n downto 0 do begin
while (p<=q) and (a[i] do begin
l[b[q]]:=i;
dec(q);
end;
inc(q);
b[q]:=i;
end;
for i:=1 to n do begin
temp:=(r[i]-l[i]-1)*a[i];
if temp>ans then ans:=temp;
end;
writeln(ans);
end.
测试数据
样例输入1【ad.in】
20
12 8 8 30 40 32 19 22 12 32 30 45 15 1937 5 5 6 26 35
样例输出1 【ad.out】
144
样例输入2 【ad.in】
56
3000 2000 180 190 2890 2900 3120 450560 500 300 2100 2300 480 840 880 890 350 550 450 760 960 860 250 260 1050 11301140 2140 2045 2065 3075 3155 3255 3470 3490 3240 920 930 900 930 980 890 740760 770 825 845 855 950 1980 880 680 690 2380 2390
样例输出2【ad.out】
21080
 
 

你可能感兴趣的:(pascal解题报告)