关于lower_bound()的用法--NYOJ 201作业题
lower_bound它有三个参数, 第一个和第二个是给定区间起点和终点的指针,第三个参数是要查找的数,它的作用原理是在给定的区间中进行二分查找,这个二分区间是前开后闭的,他返回第一个大于等于它的函数指针,例如数组 a[100] = {3, 4, 5, 6, 7, 10, 12, 34, 55}; 想找2的话,返回就返回第一个a[0]的位置,找8,就返回a[5]的位置,如果找99,比任何数都大,那么就返回数组中最后一个的下一个位置,就返回9,所以,这是可以越界的,有个测试程序,可以看下他的结果
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #include <vector> 5 using namespace std; 6 int main() 7 { 8 int a[100] = {3, 4, 5, 6, 7, 10, 12, 34, 55}; 9 int b = lower_bound(a, a + 9, 2) - a; 10 //查看数组是否改变 11 for (int i = 0; i < 9; i++) 12 printf("%d ", a[i]); 13 puts(""); 14 15 int c = lower_bound(a, a + 9, 8) - a; 16 int d = lower_bound(a, a + 9, 3) - a; 17 int e = lower_bound(a, a + 9, 455) - a; 18 printf("b = %d, c = %d, d = %d, e = %d\n", b, c, d, e); 19 20 return 0; 21 }
下面这道题,正好可以用下这个练练手,这个题就是将x拍完序之后,找 最长递增子序列,最长递减子序列 中的最大值,在找子序列位置时(用的O(nlog(n))的算法)用到这个,代码如下,也是这个题的最优代码:
#include <cstdio> #include <vector> #include <algorithm> #include <cstring> #include<functional> #define CLEAR(a, b) memset(a, b, sizeof(a)) using namespace std; const int MAX = 10000 + 10; int y[MAX], dp1[MAX], dp2[MAX]; int main() { int N; scanf("%d", &N); while (N--) { CLEAR(y, 0); CLEAR(dp1, 0); CLEAR(dp2, 0); int n; scanf("%d", &n); int x; for (int i = 0; i < n; i++) { scanf("%d", &x); scanf("%d", &y[x-1]); } int num1 = 0, num2 = 0; int num = remove(y, y + MAX, 0) - y; for (int i = 0; i < num; i++) { int *p = lower_bound(dp1, dp1 + num1, y[i]); int *q = lower_bound(dp2, dp2 + num2, y[i], greater<int>()); if (p - dp1 == num1) num1++; if (q - dp2 == num2) num2++; *p = y[i]; *q = y[i]; } printf("%d\n", max(num1, num2)); } return 0; }