p1020 导弹拦截
今天做了这道1020,感觉有点启发,来写写
先贴上代码:
1 #include <iostream> 2 #include <algorithm> 3 using namespace std; 4 const int N = 100010; 5 int a[N], d1[N], d2[N], n; 6 int main() 7 { 8 while (cin >> a[++n]); n--; 9 int len1 = 1, len2 = 1; //初始长度为1 10 d1[1] = a[1]; //不上升序列长度 11 d2[1] = a[1]; //上升序列长度 12 for (int i=2; i<=n; i++) 13 { //从a[2]开始枚举每个数(a[1]已经加进去了) 14 if(d1[len1] >= a[i]) 15 d1[++len1] = a[i]; 16 else 17 { 18 int p1 = upper_bound(d1 + 1, d1 + 1 + len1, a[i], greater<int>()) - d1; 19 d1[p1] = a[i]; 20 } 21 if (d2[len2] < a[i]) 22 d2[++len2] = a[i]; 23 else 24 { 25 int p2 = lower_bound(d2 + 1, d2 + 1 + len2, a[i]) - d2; 26 d2[p2] = a[i]; 27 } 28 } 29 cout << len1 << endl << len2; 30 return 0; 31 } 32 //lower_bound会找出序列中第一个大于等于x的数 两个都必须是升序才能使用 33 //upper_bound会找出序列中第一个大于x的数
思路:
这道题目说白了就是要求不上升序列长度和一个上升序列长度,以及运用两个STL函数lower_bound和upper_bound。
lower_bound和upper_bound注意事项:
- 两个函数必须在有序的情况下使用.且必须是升序,降序的话会出错.
- lower_bound返回的是序列中第一个>=x的数的指针(地址).
- upper_bound返回的是序列中第一个>x的数的指针(地址).
- 两个函数都是从下标0开始.
- 没错,两个函数只是相差一个 "==" O(∩_∩)O哈哈~
- 返回数组下标为:
1 int a[100] = {0,2,6,9,8,8,16,16,32,48,48,56}; 2 int p = lower_bound(a,a+n,2) - a; 3 return p;
p即为第一个>=2的数字的下标,即为1.
- 补充一下:两个函数都是可以加cmp的,但是实际意义不大....
关于最大不上升子序列:
- 使用一个数组存取,并存入序列中的第一个数字
- 遍历数组
- 无论是大还是小,一律都要放进数组中
- 分情况(如果小的话,直接压进去,小的话运用upper_bound找到位置交换)
for (int i=2; i<=n; i++) 13 { //从a[2]开始枚举每个数(a[1]已经加进去了) 14 if(d1[len1] >= a[i]) 15 d1[++len1] = a[i]; 16 else 17 { 18 int p1 = upper_bound(d1 + 1, d1 + 1 + len1, a[i], greater<int>()) - d1;//这里就是求下标 19 d1[p1] = a[i]; 20 }
关于最大上升序列:
- PS:其实原理与最大不上升序列差不多,不再赘述.
- 直接贴代码.....吱吱...
1 if (d2[len2] < a[i]) 2 d2[++len2] = a[i]; //同上 3 else 4 { 5 int p2 = lower_bound(d2 + 1, d2 + 1 + len2, a[i]) - d2; 6 d2[p2] = a[i]; 7 }

浙公网安备 33010602011771号