xjb——洛谷 P1439 排列LCS问题

来源:互联网 发布:电脑版解压软件 编辑:程序博客网 时间:2024/06/06 16:50

https://www.luogu.org/problem/show?pid=1439

这个一看就是n*n的暴力嘛,但是n有点大…
因为是两个排列,换句话说没有重复的数字;
那我们可以转化一下

比如样例

5
3 2 1 4 5
1 2 3 4 5

我们把下面一行的值变成上面一行的位置

3 2 1 4 5

那么直接最长上升子序列就好了
为什么呢?
比如第二行第一个数1
如果我们选了1,那么后面是不是只可以选择在第一行1后面的数了;
就是这个道理;

然后对于最长上升子序列我们有一个基于单调栈和二分的算法n*logn
就是维护一个递增的栈;
当前我们的值是x;
如果x>栈顶,那么直接加入;
不然我们就二分找到第一个大于x的数,直接替换;
因为x之后的数,全可以接在x的后面,所以直接替换就可以了;
最后答案就是栈的高度;
但是方案并不是栈的元素;
不好意思,这种方法不可以记录方案的;

#include<bits/stdc++.h>#define Ll long longusing namespace std;const int N=1e5+5;int f[N],a[N],v[N],top;int n,m,x,ans;int er(int x){    if(x>v[top])return ++top;    int l=1,r=top,ans,mid;    while(r>=l){        mid=l+r>>1;        if(v[mid]>x)ans=mid,r=mid-1;else l=mid+1;    }    return ans;}int main(){    scanf("%d",&n);    for(int i=1;i<=n;i++)scanf("%d",&x),f[x]=i;    for(int i=1;i<=n;i++){        scanf("%d",&x);        v[er(f[x])]=f[x];    }    printf("%d",top);}