CF #305(Div.2) D. Mike and Feet(数学推导)
Mike is the president of country What-The-Fatherland. There are n bears living in this country besides Mike. All of them are standing in a line and they are numbered from 1 to n from left to right. i-th bear is exactly ai feet high.
A group of bears is a non-empty contiguous segment of the line. The size of a group is the number of bears in that group. The strengthof a group is the minimum height of the bear in that group.
Mike is a curious to know for each x such that 1 ≤ x ≤ n the maximum strength among all groups of size x.
The first line of input contains integer n (1 ≤ n ≤ 2 × 10^5), the number of bears.
The second line contains n integers separated by space, a1, a2, ..., an (1 ≤ ai ≤ 10^9), heights of bears.
Print n integers in one line. For each x from 1 to n, print the maximum strength among all groups of size x.
10
1 2 3 4 5 4 3 2 1 6
6 4 4 3 3 2 2 1 1 1
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 const int M = 2e5 + 10 ; 5 int l[M] , r[M] , a[M] ; 6 int b[M] ; 7 int n ; 8 int main () 9 { 10 // freopen ("a.txt" , "r" , stdin ) ; 11 scanf ("%d" , &n) ; 12 for (int i = 1 ; i <= n ; i ++) scanf ("%d" , &a[i]) ; 13 a[0] = 0 ; a[n + 1] = 0 ; 14 memset (b , - 1 , sizeof(b)) ; 15 for (int i = 1 ; i <= n ; i ++) { 16 l[i] = i ; 17 while (a[l[i] - 1] >= a[i]) l[i] = l[l[i] - 1] ; 18 } 19 for (int i = n ; i >= 1 ; i --) { 20 r[i] = i ; 21 while (a[r[i] + 1] >= a[i]) r[i] = r[r[i] + 1] ; 22 } 23 for (int i = 1 ; i <= n ; i ++) { 24 int id = r[i] - l[i] + 1 ; 25 b[id] = std::max (b[id] , a[i]); 26 } 27 for (int i = n ; i >= 2 ; i --) { 28 if (b[i - 1] < b[i] ) b[i - 1] = b[i] ; 29 } 30 for (int i = 1 ; i <= n ; i ++) printf ("%d%c" , b[i] , i == n ? '\n' : ' ') ; 31 return 0 ; 32 } 33 /*10 34 1 2 3 4 5 4 3 2 1 6 35 */
- 最质补的想法,我们先考虑a[i]能影响的区间大小为w[i],(另b[i] 为长度为i的区间的最小的最大值)
for i = 1 to n
for j = 1 to w[i]
b[j] = max (b[j] , a[i]);
end
end
这样最坏情况下O(n^n),显然tle.
通过yy可以发现,区间大的可以跟新区间小的,so:
for i = 1 to n
b[w[i]] = max (b[w[i]] , a[i]);
end
for i = n to 2
if (b[i - 1] < b[i] ) b[i - 1] = b[i] ;
end
这样就变为O(n)了。
2.第二个要解决的问题时我们怎样在O(n)内求出w[i] ?
令w[i] = r[i] - l[i] ;
令r[i] , l[i]分别保存a[i]所能影响大的最右 和 最左。
这样在已知l[i]时,我们便可以在O(1)时间内求出l[i + 1]了。