洛谷P1439 最长公共子序列
传送门:
https://www.luogu.com.cn/problem/P1439
最长公共子序列可以考虑转化为最大上升子序列。很容易想到用结构体存储元素i(1<=i<=n)分别在两个序列中出现的位置,按其在第一个序列中出现的位置排序,对样例便有:
x[i].a:1 2 3 4 5
x[i].b:3 2 1 4 5
此时i在a中出现顺序一定从前往后排列,求最大公共子序列长度只需找到b中最长的上升子序列长度即可。
看下数据,n最大可以达到1e5,显然普通dp的O(n2)求法会爆,便能想到二分。
1 #include<bits/stdc++.h> 2 #define ff(i,s,e) for(int i=s;i<=e;i++) 3 using namespace std; 4 inline int read(){ 5 register int x=0,f=1;register char ch=getchar(); 6 while(ch>'9'||ch<'0'){if(ch=='-') f=-1;ch=getchar();} 7 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} 8 return x*f; 9 } 10 const int m=100005; 11 int n,f[m]; 12 struct qwq{ 13 int a,b; 14 }x[m]; 15 bool cmp(qwq x,qwq y){ 16 return x.a<y.a; 17 } 18 int find(int l,int r,int x){//二分在已知上升序列中找第一个大于x的数 19 while(l<=r){ 20 int mid=(l+r)/2; 21 if(f[mid]<x) l=mid+1; 22 else r=mid-1; 23 } 24 return l; 25 } 26 int main(){ 27 n=read(); 28 ff(i,1,n) x[read()].a=i; 29 ff(i,1,n) x[read()].b=i; 30 sort(x+1,x+n+1,cmp); 31 int len=0; 32 ff(i,1,n){ 33 if(x[i].b>f[len])//若大于当前最大上升子序列最大元素,存储 34 f[++len]=x[i].b; 35 else{f[find(1,len,x[i].b)]=x[i].b;}//用x替换大于x的数,保证后面解最优 36 } 37 printf("%d",len); 38 return 0; 39 }
                    
                
                
            
        
浙公网安备 33010602011771号