POJ 1631 Bridging signals [最长上升子序列O(nlog(n))]

描述:要为电路板搭线,要求不能交叉,如图,左边的线柱按升序排好,只需在右边线柱中找最长上升子序列。需要用二分优化。

POJ 1631 Bridging signals [最长上升子序列O(nlog(n))]_第1张图片

 

思路:在O(n*n)算法的基础上,加入一个辅助数组best[],下标表示子序列长度,对应值表示所有该长度的序列中的最小头儿,

维护这个数组,更新数组。对于新增的数x,找到位置k,使best[k-1]<x ,且best[k]>x,则best[k] = x。设best[]数组长度是sol

,可以特殊处理best[0],和best[sol-1]的情况,会发现,只有当x > best[sol-1],才会导致sol的增长。易知此序列是有序的,二分的加入就是为了找到位置k。

代码
   
   
#include < stdio.h >
#include
< string .h >
#define NL 40000

int best[NL];

int main()
{
int n, i, j, x, sol;
int T;
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
scanf( " %d " , & T);
while (T -- ) {
scanf(
" %d " , & n);
scanf(
" %d " , & best[ 0 ]);
sol
= 1 ;
for (i = 1 ; i < n; i ++ ) {
scanf(
" %d " , & x);
if (x < best[ 0 ]) {
best[
0 ] = x;
continue ;
}
if (x > best[sol - 1 ]) {
best[sol
++ ] = x;
continue ;
}
int low = 0 , high = sol - 1 , mid, ans;
while (low <= high) {
mid
= (low + high) / 2 ;
if (best[mid] < x) {
low
= mid + 1 ;
}
else {
high
= mid - 1 ;
ans
= mid;
}
}
best[ans]
= x;
}
printf(
" %d\n " , sol);
}
return 0 ;
}

 

你可能感兴趣的:(Signal)