P1020 导弹拦截|二分优化DP,

学会Dilworth定理,最长上升子序列即为最少选择的分组数(覆盖原来所有导弹)

题解:https://www.luogu.com.cn/blog/w1049/solution-p1020

#include<bits/stdc++.h>
using namespace std;

const int maxn = 100010;
int len1 = 0,len2 = 0;

int a[maxn],d1[maxn],d2[maxn];
int n = 0;
int main(){
	int d;
	while(cin>>d){
		a[++n] = d;
	}
	d1[++len1] = a[1];
	d2[++len2] = a[1];
	for(int i=2;i<=n;i++){ 
		if(d1[len1] >= a[i]){ //最长不上升子序列  不上升指可以等于 
			d1[++len1] = a[i];
		}else{
			//我们需要优化d数组, 尽可能让前面的元素大,所以查找d数组中第一个小于a[i]的元素 替换它尽能让前面的元素大 
			int pos1 = upper_bound(d1+1,d1+len1+1,a[i],greater<int>()) - d1;
			d1[pos1] = a[i];
		}
		if(d2[len2] < a[i]){ //最长上升子序列 
			d2[++len2] = a[i];
		}else{ //我们需要优化d数组, 尽可能让前面的元素小,所以查找d数组中第一个小于等于a[i]的元素
			int pos2 = lower_bound(d2+1,d2+len2+1,a[i]) - d2;
			d2[pos2] = a[i];
		}
	}
	cout<<len1<<endl;
	cout<<len2;
	return 0;
} 

类似题:牛客6-汉诺塔(LIS+定理):https://blog.csdn.net/qq_42815188/article/details/104348373

原文地址:https://www.cnblogs.com/fisherss/p/12329694.html