洛谷P1020 導彈攔截

n²誰都會打,不說了。算法

這裏討論一下nlogn算法(單調不減):ide

首先開始考慮單調性,我習慣性的覺得是單調隊列/棧優化的那個套路,想要找到一個跟下標有關的單調性卻發現沒有。優化

例如:我想過當下標增長時f[i]增長,後來發現了反例:1 3 4 2spa

事實上也沒有別的想獲得的了。code

我跑去看題解,發現單調性是這個毒瘤:blog

當單調不減子序列長度增長時,每一個長度對應的最小高度增長。隊列

而後每次二分出一個長度,保證最小高度恰好不大於a[i]string

而後用a[i]更新f[i]的最小高度...it

而後就沒啥難點了,A了。io

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 
 5 const int N = 100010;
 6 
 7 int a[N], f[N], p[N], top;
 8 
 9 inline int BS(int x) {
10     int l = 0, r = top, mid;
11     while(l < r) {
12         mid = (l + r + 1) >> 1;
13         if(p[mid] < x) {
14             r = mid - 1;
15         }
16         else {
17             l = mid;
18         }
19     }
20     return r;
21 }
22 
23 inline int BS2(int x) {
24     int l = 0, r = top, mid;
25     while(l < r) {
26         mid = (l + r + 1) >> 1;
27         if(p[mid] >= x) {
28             r = mid - 1;
29         }
30         else {
31             l = mid;
32         }
33     }
34     return r;
35 }
36 
37 int main() {
38     int n = 0, x;
39     while(scanf("%d", &x) != -1) {
40         a[++n] = x;
41     }
42     for(int i = 1; i <= n; i++) {
43         int t = BS(a[i]);
44         f[i] = t + 1;
45         p[f[i]] = std::max(p[f[i]], a[i]);
46         top = std::max(top, f[i]);
47     }
48     printf("%d \n", top);
49     top = 0;
50     memset(p, 0x7f, sizeof(p));
51     for(int i = 1; i <= n; i++) {
52         int t = BS2(a[i]);
53         f[i] = t + 1;
54         p[f[i]] = std::min(p[f[i]], a[i]);
55         top = std::max(top, f[i]);
56     }
57     printf("%d", top);
58     return 0;
59 }
AC代碼

附一張提交記錄

相關文章
相關標籤/搜索