bzoj1057本质上是求最大子矩阵;
第一问是一个经典的O(n2)dp
第二问就是最大子矩阵,回眸一下当年卡了我很久的问题;
首先穷举显然不行(这不废话吗?);
首先我们预处理每个点可以最大向上延展到哪里;
然后我们一行一行看每个点能以最大延展高度向左右延展到多少
这其中的最大值即answer;
初看处理每行上点左右延展距离为O(n2)
实际上是可以以O(n)搞定的
单调队列?确实可以,但是很烦……
分左延展右延展两种情况考虑
用l[j]表示这行上列为j的点最远可以延伸到哪个点,然后
l[j]:=j;
while (l[j]>0) and (h[j]<=h[l[j]-1]) do l[j]:=l[l[j]-1];
妙哉,问题得解;
由这种思路,我以迅雷不急掩耳之势拍出poj3250,不到20行代码141MS过,不错!
1 var a,d:array[0..80010] of longint; 2 p,i,n,m:longint; 3 s:int64; 4 begin 5 readln(n); 6 for i:=n downto 1 do 7 readln(a[i]); 8 a[0]:=2147483647; 9 d[1]:=1; 10 for i:=2 to n do 11 begin 12 d[i]:=i; 13 while a[i]>a[d[i]-1] do d[i]:=d[d[i]-1]; 14 s:=s+i-d[i]; 15 end; 16 writeln(s); 17 end.