题意是找出让连线不交错的最大剩余线的个数
一看题就知道是求最长上升子序列
但是,看看数据范围就知道,很明显普通的LIS算法会超时
这个时候,我们就要优化。
多创建一个d数组和int len 变量,d[len] 表示长度为len的上升子序列的最后一个元素,如果读入一个数,它的值为x,有d[i] < x < d[i+1]的话,我们就把d[i+1] 赋值为 x,当然,如果i+1>len的话,len++。
利用d数组的单调性我们可以轻松用log n的复杂度找到 上面的那个i
最后算出的len就是答案。
下面贴代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
const int maxn = 40010;
//int a[maxn];一开始我还想保存所有读入的数,事实证明我想多了,没必要
int d[maxn];
int main()
{
int t;
scanf("%d",&t);
while(t--){
int p,x;
scanf("%d",&p);
scanf("%d",&x);
int len = 1;
d[len] = x;
for(int i=1;i<p;i++){
scanf("%d",&x);
int t = lower_bound(d+1,d+len+1,x) - (d+1);
//printf("%d t\n",t);
if(t==len){
len++;
d[len] = x;
}else {
d[t+1] = x;
}
}
printf("%d\n",len);
}
return 0 ;
}
如果觉得我讲的不好,请参考最长上升子序列(LIS)n*log n 算法