dilworth 定理: 最小链划分数 = 最大反链的长度。
于是先按照l 或者 w 排序, 再求最大递减子序列的长度即可~
要注意,第一次按照 l 排序时(按w 思路也一样),如果出现l相同的情况, 那么应该再在l相同的木头之间比较w, 并且把w最小的木头放在前面。
如: ( l , w ) = (5,3) (5,2 ) (5, 1) 则要排成 (5,1) (5,2) (5,3)。
#include<iostream>
using namespace std;
int l[5002];
int w[5002];
int ln[5002];
int T;
inline void swap_(int &a, int &b)
{
int tmp;
tmp = a;
a = b;
b = tmp;
}
void fast_sort(int top, int bot)
{
if(top < bot)
{
int j = top;
for(int i = top ; i < bot ; i ++)
{
if(l[i] < l[bot])
{
swap_(l[i],l[j]);
swap_(w[i],w[j]);
j++;
}
else if(l[i]==l[bot] && w[i]<w[bot])
{
swap_(w[i],w[bot]);
}
}
swap_(l[j],l[bot]);
swap_(w[j],w[bot]);
fast_sort(top,j-1);
fast_sort(j+1,bot);
}
}
int ln_len(const int &n_)
{
int len = 0;
for(int i = 0 ; i < n_ ; i++)
{
int top = 1;
int bot = len;
int mid;
while(top <= bot)
{
mid = (top+bot)/2;
if( ln[mid] > w[i])top = mid+1;
else bot = mid-1;
}
ln[top] = w[i];
if(top > len)len++;
}
return len;
}
int main()
{
int n,res;
ln[0] = 10001;
scanf("%d",&T);
while(T)
{
scanf("%d",&n);
for(int i = 0 ; i < n ; i++)scanf("%d%d",&l[i],&w[i]);
fast_sort(0,n-1);
res = ln_len(n);
printf("%d\n",res);
T--;
}
return 0;
}