題意是找出讓連線不交錯的最大剩餘線的個數
一看題就知道是求最長上升子序列
但是,看看數據範圍就知道,很明顯普通的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 算法