P3402 最长公共子序列

P3402 最长公共子序列
经典问题
LCS-->LIS

没有重复的值才可以这么做
把第一数列转化成1~n,然后将第二个数列映射成1~n中的一些数,然后求第二个数列的LIS即可,然后用Bit求LIS,O(nlogN)

//数据太大,考虑map

#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<map>
#include<cstring>
#define inf 2147483647
#define For(i,a,b) for(register int i=a;i<=b;i++)
#define p(a) putchar(a)
#define g() getchar()
//by war
//2017.10.17
using namespace std;
int n,m;
int t[300010];
int ans;
int f[300010];
int a[300010];
int b[300010];
int x;
map<int,int>c;
void in(int &x)
{
    int y=1;
    char c=g();x=0;
    while(c<'0'||c>'9')
    {
    if(c=='-')
    y=-1;
    c=g();
    }
    while(c<='9'&&c>='0')x=x*10+c-'0',c=g();
    x*=y;
}
void o(int x)
{
    if(x<0)
    {
        p('-');
        x=-x;
    }
    if(x>9)o(x/10);
    p(x%10+'0');
}

int getmax(int k)
{
    int Max=0;
    for(;k>0;k-=(-k)&k)
    Max=max(Max,t[k]);
    return Max;
}

void modify(int k,int Max)
{
    for(;k<=n;k+=(-k)&k)
    t[k]=max(t[k],Max);
}

int main()
{
    in(n),in(m);
    For(i,1,n)
    in(b[i]),c[b[i]]=i;
    For(i,1,m)
    in(a[i]);
    For(i,1,m)
    a[i]=c[a[i]];
    For(i,1,m)
    {
        f[i]=getmax(a[i])+1;
        ans=max(ans,f[i]);
        if(a[i]>0)
        modify(a[i],f[i]);
    }
    o(ans);
     return 0;
}
View Code

我今天才算搞懂最长公共子序列的nlogn的做法,下面的是任何情况都适用的

5 4 1 1 2
1 2 4,3 4,3 5

1 1 4
4 3 4 3 5

在4 3 4 3 5里面求严格递增的LIS就是二者的LCS

#include <bits/stdc++.h>
#define inf 2147483647
#define N 1000010
#define p(a) putchar(a)
#define For(i,a,b) for(long long i=a;i<=b;++i)
//by war
//2020.4.24
using namespace std;
long long n,m,cnt;
long long t[N],a[N],b[N],temp[N];
long long ans0,ans1;
long long x;
map<long long,long long>c,d;
vector<long long>v[N],u;
stack<int>st;
void in(long long &x){
    long long y=1;char c=getchar();x=0;
    while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
    while(c<='9'&&c>='0'){ x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    x*=y;
}
void o(long long x){
    if(x<0){p('-');x=-x;}
    if(x>9)o(x/10);
    p(x%10+'0');
}

long long getmax(long long k){
    long long Max=0;
    for(;k>0;k-=(-k)&k) 
        Max=max(Max,t[k]);
    return Max;
}

void modify(long long k,long long Max){
    for(;k<=cnt;k+=(-k)&k)
          t[k]=max(t[k],Max);
}

signed main(){
    in(n);in(m);
    For(i,1,n){
        in(b[i]);
        if(c[b[i]]==0){
            c[b[i]]=i;
            v[i].push_back(i);
        }
        else v[c[b[i]]].push_back(i);
        temp[i]=b[i];
    }
    sort(temp+1,temp+n+1);
    For(i,1,n) d[temp[i]]=i;
    For(i,1,n) b[i]=d[b[i]],u.push_back(b[i]);
    cnt=u.size();
    for(auto i:u){
        long long cc=getmax(i-1)+1;
        ans0=max(ans0,cc);
        modify(i,cc);
    }
    u.clear();
    For(i,1,m) in(a[i]);
    For(i,1,m){
        if(c[a[i]]!=0){
            for(auto j:v[c[a[i]]])
                st.push(j);
            while(!st.empty()) u.push_back(st.top()),st.pop();
        }
    }
    memset(t,0,sizeof(t));
    for(auto i:u){
        long long cc=getmax(i-1)+1;
        ans1=max(ans1,cc);
        modify(i,cc);
    }
    o(ans0);p(' ');o(ans1);
    return 0;
}
原文地址:https://www.cnblogs.com/war1111/p/7682443.html