思路:
Problem1: 第一个问题就是求最长不上升子序列长度
Problem2: 第二个问题看上去有些难, 但是通过组合数学中的"Dilworth定理"可以知道"最少的下降序列个数就等于整个序列最长上升子序列的长度", 所以第二个问题就是求最长上升子序列长度
/**
* 题目: 洛谷OJ P1020 导弹拦截
* 题型: DP
**/
#include <cstdio>
#include <iostream>
using namespace std;
const int maxn = 100000+10;
int a[maxn], b[maxn], n, ans;
int main() {
/************input**************/
while(scanf("%d", &a[++n]) != EOF);
n--;
/*******************************/
//Problem 1
ans = 1; b[1] = a[1];
for(int i = 2; i <= n; i++) {
if(a[i] <= b[ans]) b[++ans] = a[i];
else {
int l = 1, r = ans;
while(r > l) { //找出比a[i]小的元素中最大的那个并替换它
int mid = (l + r) / 2;
if(a[i] > b[mid]) r = mid;
else l = mid+1;
}
b[r] = a[i];
}
}
cout << ans << endl;
//Problem 2
ans = 1; b[1] = a[1];
for(int i = 2; i <= n; i++) {
if(a[i] > b[ans]) b[++ans] = a[i];
else {
int l = 1, r = ans;
while(r > l) { //找出比a[i]大的元素中最小的元素并替换它
int mid = (l + r) / 2;
if(a[i] <= b[mid]) r = mid;
else l = mid+1;
}
b[r] = a[i];
}
}
cout << ans << endl;
return 0;
}