给出长度为n,m的序列a,b,求出最长公共子序列
n,m<=300000
时间限制1s
空间限制256M
先离散化,把b[i]在序列a中出现的位置pos[i]求出来,然后求一个最长上升子序列。
#include
#include
#include
#define maxn 300006
#define fr(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
struct nod
{
int x,y,z;
} d[maxn+maxn];
bool cmp(nod a,nod b)
{
return a.xx;
}
int i,n,m,s,tot,ans,a[maxn],b[maxn],pos[maxn],f[maxn],tr[maxn*4];
void modify(int v,int st,int en,int x,int y)
{
if (st==en)
{
tr[v]=y;
return;
}
int m=(st+en) >> 1;
if (x<=m) modify(v+v,st,m,x,y);
else modify(v+v+1,m+1,en,x,y);
tr[v]=max(tr[v+v],tr[v+v+1]);
return;
}
void findd(int v,int st,int en,int l,int r)
{
if (st==l && en==r)
{
s=max(s,tr[v]);
return;
}
int m=(st+en) >> 1;
if (r<=m) findd(v+v,st,m,l,r);
else if (l>m) findd(v+v+1,m+1,en,l,r);
else
{
findd(v+v,st,m,l,m);
findd(v+v+1,m+1,en,m+1,r);
}
return;
}
int main()
{
scanf("%d%d",&n,&m);
fr(i,1,n)
{
scanf("%d",&a[i]);
d[i].x=a[i],d[i].y=i,d[i].z=1;
}
fr(i,1,m)
{
scanf("%d",&b[i]);
d[n+i].x=b[i],d[n+i].y=i,d[n+i].z=2;
}
sort(d+1,d+n+m+1,cmp);
int k=0;
d[0].x=1 << 30;
fr(i,1,n+m)
{
if (d[i].x!=d[i-1].x) ++k;
if (d[i].z==1) a[d[i].y]=k;
else b[d[i].y]=k;
}
fr(i,1,n) pos[a[i]]=i;
fr(i,1,m) b[i]=pos[b[i]];
fr(i,1,m)
{
s=0;
if (b[i]) findd(1,0,m,0,b[i]-1);
else continue;
f[i]=s+1;
modify(1,0,m,b[i],f[i]);
ans=max(ans,f[i]);
}
printf("%d\n",ans);
return 0;
}