原题链接:http://www.spoj.com/problems/SUPPER/
这道题n<=200000,那么确定为nlogn的算法,再定位到求LIS的O(nlogn)的算法。
对于每个a[i],求出其向左能延伸的元素个数L[i]和向右能延伸的元素个数R[i],所有位置L[i]+R[i]为最大值的元素排序输出即可。
心得:
1.求LIS的O(nlogn)算法能解决子区间的LIS问题,所以经常出现在题目中,要灵活运用。
2.lower_bound函数有cmp函数参数可以选择升序查找(less<int>())或降序查找(greater<int>())。
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #include <vector> 5 #include <queue> 6 using namespace std; 7 8 #define N 100005 9 10 int a[N], L[N], R[N], n, m, d[N]; 11 vector<int> vt; 12 13 int main() 14 { 15 for(int cas = 1; cas <= 10; cas++) 16 { 17 scanf("%d", &n); 18 for(int i = 0; i < n; i++) 19 scanf("%d", &a[i]); 20 vt.clear(); 21 for(int i = 0; i < n; i++) 22 { 23 int j = lower_bound(vt.begin(), vt.end(), a[i], less<int>()) - vt.begin(); 24 if(j == vt.size()) 25 vt.push_back(a[i]); 26 else 27 vt[j] = min(vt[j], a[i]); 28 L[i] = j; 29 } 30 vt.clear(); 31 for(int i = n - 1; i >= 0; i--) 32 { 33 int j = lower_bound(vt.begin(), vt.end(), a[i], greater<int>()) - vt.begin(); 34 if(j == vt.size()) 35 vt.push_back(a[i]); 36 else 37 vt[j] = max(vt[j], a[i]); 38 R[i] = j; 39 } 40 m = 0; 41 for(int i = 0; i < n; i++) 42 if(L[i] + R[i] > m) m = L[i] + R[i]; 43 int k(0); 44 for(int i = 0; i < n; i++) 45 { 46 if(L[i]+R[i] == m) 47 { 48 d[k++] = a[i]; 49 } 50 } 51 sort(d, d+k); 52 printf("%d ", k); 53 for(int i = 0; i < k; i++) 54 { 55 if(i != 0) putchar(' '); 56 printf("%d", d[i]); 57 } 58 putchar(' '); 59 } 60 return 0; 61 }