用到了dilworth定理:链的最少划分数=反链的最长长度(没有验证过)。如4、1、5、9、2的最少的非递减子序列的个数就是其最大递减子序列长度。
采用两种方法具体见:poj 2533做题笔记 。前一个110MS,后一个16MS。差别还是蛮大的。
代码如下:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=5010;
struct node{
int a;
int b;
}sticks[N];
bool cmp(node a,node b)
{
if(a.a==b.a)
return a.b<b.b;
else
return a.a<b.a;
}
int main()
{
int t,n,i,j;
int dp[N];
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d%d",&sticks[i].a,&sticks[i].b);
sort(sticks+1,sticks+n+1,cmp);
int maxn=0;
for(i=1;i<=n;i++)
{
dp[i]=1;
for(j=1;j<i;j++)
if(sticks[i].b<sticks[j].b&&dp[i]<dp[j]+1)
dp[i]=dp[j]+1;
if(maxn<dp[i])maxn=dp[i];
}
printf("%d\n",maxn);
}
return 0;
}
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=5010;
struct node{
int a;
int b;
}sticks[N];
bool cmp(node a,node b)
{
if(a.a==b.a)
return a.b<b.b;
else
return a.a<b.a;
}
int main()
{
int t,n,i,top;
int dp[N];
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d%d",&sticks[i].a,&sticks[i].b);
sort(sticks+1,sticks+n+1,cmp);
top=0,dp[0]=101000;
for(i=1;i<=n;i++)
{
if(sticks[i].b<dp[top])
dp[++top]=sticks[i].b;
else
{
int low=1,high=top;
while(low<=high)
{
int mid=(low+high)/2;
if(sticks[i].b<dp[mid])
low=mid+1;
else
high=mid-1;
}
dp[low]=sticks[i].b;
}
}
printf("%d\n",top);
}
return 0;
}