题目链接:
https://www.luogu.com.cn/problem/P1020

参考:
http://www.cnblogs.com/GodA/p/5180560.html
https://www.luogu.com.cn/blog/w1049/solution-p1020

题解:
第一行:
为从1到n的最长非升子序列的个数。
第二行:
Dilworth定理:偏序集能划分成的最少的全序集的个数==最大反链的元素个数。
故为从1到n最长单调升序列的个数。

DP
O(n^2):

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAXN = 1e5 + 5;

int a[MAXN];
int f[MAXN];
int p[MAXN];

int main(){
// freopen("test.in","r",stdin);
// freopen("test1.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	int ans=1;
	int tot=1;
	int n=0;
	while(cin>>a[++n]);
	for(int i=1;i<n;i++){
		f[i]=1;
		p[i]=1;
		for(int j=1;j<i;j++){
			if(a[i]<=a[j]) f[i]=max(f[i],f[j]+1);
			if(a[i]>a[j]) p[i]=max(p[i],p[j]+1);
		}
		ans=max(ans,f[i]);
		tot=max(tot,p[i]);
	}
	cout<<ans<<endl;
	cout<<tot<<endl;	
	return 0;
}

二分+贪心
O(nlogn):

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAXN = 1e5 + 5;

int a[MAXN];
int f1[MAXN];
int f2[MAXN];

int main(){
// freopen("test.in","r",stdin);
// freopen("test3.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	int len1=1,len2=1,n=0;
	while(cin>>a[++n]) ;
	f1[1]=f2[1]=a[1];
	for(int i=2;i<n;i++){
		if(a[i]<=f1[len1]){
			f1[++len1]=a[i];
		}else{
			*upper_bound(f1+1,f1+1+len1,a[i],greater<int>() )=a[i];
		}
		if(a[i]>f2[len2]){
			f2[++len2]=a[i];
		}else{
			*lower_bound(f2+1,f2+1+len2,a[i])=a[i];
		}
	}
	cout<<len1<<endl;
	cout<<len2<<endl;
	return 0;
}