洛谷P1020 导弹拦截【LIS 贪心+二分】

题目链接:P1020 导弹拦截
洛谷P1020 导弹拦截【LIS 贪心+二分】_第1张图片

程序说明:

第一个问题是求最长非上升子序列。upper_bound和lower_bound只能对非递减序列进行查找,由题可知 f 数组是单调递减的,因此需要在upper_bound函数中多一个参数:greater()或者手写cmp。

第二个问题是求最长上升子序列(Dilworth定理),证明的方法可以参考大佬的博客:DP-导弹拦截。即最长上升子序列和最大非上升子序列的划分个数相等。

代码如下:

#include 
#include 
using namespace std;

const int N = 100010;

int a[N], f[N], g[N], n, m, cnt;

int main() {
	while(cin>>a[++cnt]);
	cnt--; //cnt是导弹的个数,这里要减去1
	f[++n] = a[1];
	g[++m] = a[1];
	
	for(int i = 2; i <= cnt; i++) {	
		if(a[i] <= f[n])
			f[++n] = a[i];
		else {
			//这里用upper_bound是因为相等的数字要保留
			int *t = upper_bound(f + 1, f + n + 1, a[i], greater<int>());
			f[t - f] = a[i];
		}
		 
		if(a[i] > g[m])
			g[++m] = a[i];
		else {
			int *t = lower_bound(g + 1, g + m + 1, a[i]);
			g[t - g] = a[i];
		}
	}
	
	cout<<n<<endl<<m;	
	return 0;
}

你可能感兴趣的:(算法题解,#,动态规划,#,贪心)