Bridging signals
subject
"Oh, no, they did it again," shouted the chief designer of Waferland chip factory. The wiring designer completely screwed up again, making the signals on the chip connecting the two function block ports cross each other everywhere. At a later stage of the process, the cost of rerouting is too high. Instead, engineers must use the third dimension to bridge signals so that the two signals do not cross. However, bridging is a complex operation, so it is desirable to bridge as few signals as possible. A computer program is urgently needed to find the maximum number of signals that can be connected on the silicon surface without crossing each other. Remember that there may be thousands of signal ports at the boundary of function blocks, which puts forward many requirements for programmers. Are you qualified for the task?
Fig. 1 schematically depicts a typical case. The ports of the two function blocks are numbered from 1 to p and from top to bottom. The signal mapping is described by the numbers 1 to p in the form of a list of p unique numbers in the range 1 to p, where the ith number specifies which port on the right should be connected to I: the first port on the left. When and only when the straight lines connecting each pair of two ports cross, the two signals cross.
thinking
 Translate intersection into mathematical language, i.e
a
[
i
]
>
a
[
j
]
a[i] > a[j]
A [i] > a [J] where
a
[
i
]
a[i]
a[i] represents the second
i
i
Number of link points at i locations
Keep as disjoint a [ i ] < a [ j ] ( i < j ) a[i]<a[j] (i<j) A [i] < a [J] (I < J), so it is obvious that this is the longest ascending subsequence problem (LIS)  Due to data size 40000 40000 40000, so O ( n ∗ n ) O(n*n) The algorithm of O(n * n) cannot be solved, so it is selected O ( n l o g n ) O(nlogn) O(nlogn) algorithm
DP algorithm O ( n ∗ n ) O(n*n) O(n∗n)

definition d p [ i ] dp[i] dp[i] is an ascending subsequence ending with I

State transition must be from d p [ 1 , i − 1 ] dp[1 , i1] Maximum value of dp[1,i − 1] + 1
Namely: d p [ i ] = m a x ( d p [ 1 , j ] ) + 1 dp[i] = max(dp[1,j])+1 dp[i]=max(dp[1,j])+1 ( a [ i ] > a [ j ] And j < i ) (a [i] > a [J] and j < I) (a [i] > a [J] and j < I)
#include<iostream> #include<cstdio> #include<algorithm> #include<string> #include<cstring> #include<vector> #include<queue> #include<set> #include<map> #include<fstream> #define inf 0x3f3f3f3f #define ll long long #define linf 0x3f3f3f3f3f3f3f3f #define ull unsigned long long #define endl '\n' //#define int long long using namespace std; typedef pair<int,int> PII; const int N =10 + 4e4 ,mod=1e9 + 7; int dp[N]; int n; int a[N]; void solve() { cin>>n; for(int i=1;i<=n;i++)cin>>a[i]; memset(dp,0,sizeof dp); for(int i=2;i<=n;i++)// O(n^2) { dp[i] = 1; for(int j=i1;j>=1;j) if(a[i]>a[j]) dp[i] = max(dp[i],dp[j] + 1); } int res=0; for(int i=1;i<=n;i++) res = max(res,dp[i]); cout << res <<endl; } signed main() { ios::sync_with_stdio();cin.tie();cout.tie(); int T;cin>>T; while(T) solve(); //cerr<<endl<<" Time : "<< T2T1 <<"ms."<<endl; return 0; }
Obviously, the algorithm can not solve this problem
Greed + dichotomy O ( n ∗ l o g n ) O(n*logn) O(n∗logn)

We maintain an ascending sequence of records with a length of i i An array of minimum end values when i l i s [ n ] lis[n] lis[n].
The maximum length of this array is the desired length 
The correctness of this algorithm will not be rigorously proved
For the time being, the smaller the end, the more conducive it is to form the longest rising sequence 
Because the maintenance process is always looking for a [ i ] a[i] The sequence is ordered, so it can be optimized by dichotomy
#include<iostream> #include<cstdio> #include<algorithm> #include<string> #include<cstring> #include<vector> #include<queue> #include<set> #include<map> #include<fstream> #define inf 0x3f3f3f3f #define ll long long #define linf 0x3f3f3f3f3f3f3f3f #define ull unsigned long long #define endl '\n' //#define int long long using namespace std; typedef pair<int,int> PII; const int N =10 + 4e4 ,mod=1e9 + 7; int dp[N]; int n; int a[N]; void solve() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",a+i); vector<int>lis(n); { for(int i=0;i<n;i++)lis[i] = inf; } for(int i=1;i<=n;i++) { int p = lower_bound(lis.begin(),lis.end(),a[i])  lis.begin(); lis[p] = a[i]; } printf("%d\n",lower_bound(lis.begin(),lis.end(),inf)  lis.begin()); } signed main() { // ios::sync_with_stdio();cin.tie();cout.tie(); int T;cin>>T; while(T) solve(); //cerr<<endl<<" Time : "<< T2T1 <<"ms."<<endl; return 0; }