您的位置:首页 > 其它

poj 1631 Bridging signals LIS 最长非递减子序列

2016-11-14 20:25 309 查看
#include <iostream>
#include <cstdio>

/************************************************

designer:hl
time:2016/11/14
Exe.Time:125 ms
Exe.Memory:832 KB

题目链接:http://poj.org/problem?id=1631

题意:意思是不要交叉。问最多能连接几个。可以直接转化成LIS

题解:LIS好题。用一般的dp[i]=max(dp[i],dp[j-1]+1)的方法会超时。后来加了一个小优化,如果剩下的j的数量小于现有的dp[j]
则直接跳出。还是超时。于是使用了nlog(n)的方法来解决这个问题

需要的是建立一个dp[]数组 第i个的元素x代表着在长度为i的最大非递减子序列中,能取到的最小的尾部是x
比如 1 3 2 4
dp[1]=1 当看到第二个数的时候 dp[2]=3 当看到第三个数字的时候 2比3小 明显更优 所以dp[2]=2 以此类推。得到最长费递减
子序列的长度
************************************************/

using namespace std;

int dp[40044];

void erfen(int left, int right, int t) {
int half = 1;
while (left < right) {
half = (left + right) >> 1;
if (dp[half] < t) {
left = half + 1;
} else {
right = half;
}
}
dp[left] = t;

}

int main() {

int i, j, k, l, t, count, num;
scanf("%d", &count);
while (count--) {
scanf("%d", &num);
scanf("%d", &t);
dp[1] = t;
for (i = 2, j = 1; i <= num; i++) {
scanf("%d", &t);
if (t > dp[j]) {
dp[++j] = t;
} else {
erfen(1, j, t);
}
}

/* for(i=1;i<=j;i++){
printf("%d  ",dp[i]);
}
printf("\n");*/
printf("%d\n", j);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  DP