HDU 1950-Bridging signals

题目链接→HDU 1950 Bridging signals

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 50025    Accepted Submission(s): 19592

【dp-LIS】HDU 1950-Bridging signals (LIS模板题)_ide Problem Description


'Oh no, they've done it again', cries the chief designer at the Waferland chip factory. Once more the routing designers have screwed up completely, making the signals on the chip connecting the ports of two functional blocks cross each other all over the place. At this late stage of the process, it is too
expensive to redo the routing. Instead, the engineers have to bridge the signals, using the third dimension, so that no two signals cross. However, bridging is a complicated operation, and thus it is desirable to bridge as few signals as possible. The call for a computer program that finds the maximum number of signals which may be connected on the silicon surface without rossing each other, is imminent. Bearing in mind that there may be housands of signal ports at the boundary of a functional block, the problem asks quite a lot of the programmer. Are you up to the task?

【dp-LIS】HDU 1950-Bridging signals (LIS模板题)_ico_02

Figure 1. To the left: The two blocks' ports and their signal mapping (4,2,6,3,1,5). To the right: At most three signals may be routed on the silicon surface without crossing each other. The dashed signals must be bridged. 
  A typical situation is schematically depicted in figure 1. The ports of the two functional blocks are numbered from 1 to p, from top to bottom. The signal mapping is described by a permutation of the numbers 1 to p in the form of a list of p unique numbers in the range 1 to p, in which the i:th number pecifies which port on the right side should be connected to the i:th port on the left side.
  Two signals cross if and only if the straight lines connecting the two ports of each pair do.

【dp-LIS】HDU 1950-Bridging signals (LIS模板题)_ide Input


On the first line of the input, there is a single positive integer n, telling the number of test scenarios to follow. Each test scenario begins with a line containing a single positive integer p<40000, the number of ports on the two functional blocks. Then follow p lines, describing the signal mapping: On the i:th line is the port number of the block on the right side which should be connected to the i:th port of the block on the left side.

【dp-LIS】HDU 1950-Bridging signals (LIS模板题)_ide Output


For each test scenario, output one line containing the maximum number of signals which may be routed on the silicon surface without crossing each other.


【dp-LIS】HDU 1950-Bridging signals (LIS模板题)_ide Sample Input

4
6
4
2
6
3
1
5
10
2
3
4
5
6
7
8
9
10
1
8
8
7
6
5
4
3
2
1
9
5
8
9
2
3
1
7
4
6


【dp-LIS】HDU 1950-Bridging signals (LIS模板题)_ide Sample Output

3
9
1
4


【dp-LIS】HDU 1950-Bridging signals (LIS模板题)_ide Problem Idea

解题思路:

【题意】

  本题的题目个人觉得不是一般的难懂,况且还是英文的。

  真正题意:从左侧的图中去掉一些线段使剩余的线段都不相交,问最多能够剩下多少条线段?
  由观察可知要想剩下的线段都不相交,则要求右侧线为单调递增的排序。

  这题是一个经典的布线问题, 如下图所示: 左右各有n(n<40000)个点, 原本左边的每个点分别跟右边的一个点相连(不会有两个左边的点连同一个右边的点), 要求我们拆除一部分线, 保留尽可能多的线, 使得剩下的线两两不能有交点.

  记左边的两个点为i, j且i < j, 与之相连的右边的点分别为a[i], a[j], 则两条线不相交的充要条件就是: a[i]<a[j], 于是这个问题转化成了经典的LIS.但是这题与一般题最大的差别就在于: 数组的长度太大了, 由1000变到了40000, 于是O(n^2)复杂度基本只有超时的命运, 所以我们必须想办法优化.

  对于给出的测试样例,这样看会更正常一些:

样例这样看更正常
Sample Input
4
6 
4 2 6 3 1 5
10
2 3 4 5 6 7 8 9 10 1
8
8 7 6 5 4 3 2 1
9
5 8 9 2 3 1 7 4 6

【类型
  动态规划--最长上升子序列(LIS)
【分析】

  本题的实质就是一个“最长上升子序列”的问题(LIS),

  记左边的两个点为i, j且i < j, 与之相连的右边的点分别为a[i], a[j], 则两条线不相交的充要条件就是: a[i]<a[j], 于是这个问题转化成了经典的LIS.但是这题与一般题最大的差别就在于: 数组的长度太大了, 由1000变到了40000, 如若采用普通的最长上升序列算法时间复杂度是O(n*n),显然会超时, 所以我们必须想办法优化。  

  因此套用O(nlogn)的算法模板。

【时间复杂度&&优化】
  O(nlogn)

【dp-LIS】HDU 1950-Bridging signals (LIS模板题)_ide Source Code

#include <iostream>
using namespace std;
int a[40010],dp[40010];
const int INF=0x3f3f3f;
int main() {
    int T,n;
    cin>>T;
    while(T--){
        cin>>n;
        for(int i=0;i<n;i++){
            cin>>a[i];
            dp[i]=INF;
        }
        for(int i=0;i<n;i++){
            *lower_bound(dp,dp+n,a[i])=a[i];
        }
        cout<<lower_bound(dp,dp+n,INF)-dp<<endl;
    }
    return 0;
}