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

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

 

思路:在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;
}

 

posted @ 2010-07-13 08:29  superbin  阅读(386)  评论(0编辑  收藏  举报