洛谷P1439 【模板】最長公共子序列
阿新 • • 發佈:2020-10-31
這題的思路太妙了
思路
首先我作為一個蒟蒻,只能想到50分的做法,而且由於太好想了幾乎是秒出答案。但是100分做法我直接放棄想了。。。因為我也意識到自己\(dp\)太菜了不可能想出來。但是看到了一篇絕妙的題解,直接把這題秒了。簡而言之,首先,答案序列一定是\(A\)的子序列,由於兩個序列都是1~n的,那麼我們可以強制將\(A\)陣列變為順序,然後在\(B\)陣列中對應修改,再求出\(B\)陣列的最長上升子序列。
比如說樣例中\(A\)={3,2,1,4,5}。那麼我將\(A\)強制變為{1,2,3,4,5},將每個數的數值對應到下標,再將\(B\)序列轉化成下標,求最長上升子序列即可。正確性其實很顯然,因為子序列一定在\(A\)
程式碼
\(O(nlogn)\)求最長上升子序列板子不解釋
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<queue> #include<ctime> using namespace std; typedef long long ll; int n; int a[100005],b[100005],map[100005],f[100005],len; int main() { scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); map[a[i]]=i; } for(int i=1;i<=n;i++){ scanf("%d",&b[i]); b[i]=map[b[i]]; } f[0]=0; for(int i=1;i<=n;i++){ if(b[i]>f[len]){ f[++len]=b[i]; } else{ int p=upper_bound(f+1,f+1+len,b[i])-f; f[p]=b[i]; } } printf("%d\n",len); return 0; }