题目链接:https://www.luogu.org/problemnew/show/P1020
思路:首先第一问:最多能拦下多少导弹的答案是给出数列的最长不递增子序列的长度。(这个不难想到)而第二问:至少几套导弹系统的答案是给出数列的最长递增子序列的长度。
c++代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <map>
using namespace std;
const int maxn=1e5+5;
int a[maxn];
int b[maxn];
int n;
int mfind(int left,int right,int x) {
//if(left>right)return 0;//应对开始时b中没有数的情况
if(b[right]>=x)return right+1;
while(left<right) {
int mid=(left+right)/2;
if(b[mid]>=x)left=mid+1;
else right=mid;
}
return right;
}
int mfind1(int left,int right,int x) {
//if(left>right)return 0;//应对开始时b中没有数的情况
if(b[right]<x)return right+1;
while(left<right) {
int mid=(left+right)/2;
if(b[mid]<x)left=mid+1;
else right=mid;
}
return left;
}
int main() {
n=0;
while(scanf("%d",&a[n])!=EOF)n++;
memset(b,0,sizeof(b));
int cnt=1;
//cout << n <<endl;
b[0]=a[0];
for(int i=1;i<n;i++) { //求最长不递增子序列
int p=mfind(0,cnt-1,a[i]);
//cout << p <<endl;
if(p<cnt) {
b[p]=a[i];
//cout << b[p] << endl;
}
else {
b[cnt++]=a[i];
//cout << cnt << endl;
}
}
cout << cnt << endl;
b[0]=a[0];
int ans=1;
for(int i=1;i<n;i++) { //求最长递增子序列
int p=mfind1(0,ans-1,a[i]);
if(p<ans) {
b[p]=a[i];
}
else {
b[ans++]=a[i];
}
}
cout << ans << endl;
return 0;
}