树状数组优化DP
毒瘤题
暴力60分!
讲讲思路
最暴力的思路就是
n
2
n^2
n2求LCS,能拿到60分得好成绩,如何AC?我也不会,这道题中每个元素都出现了5次,这是个很好的性质,也就是说两个序列的元素是一样的所以我们不妨存下第一个串中每个元素都在哪个地方出现过,那么我们在用第二个串匹配时,直接找到当前元素在a串中出现的位置,因为只有在这些位置才可能有贡献,然后我们用树状数组维护一下每个位置上的LCS,然后每次对于元素
b
[
i
]
b[i]
b[i],枚举出现的位置,然后更新,注意,我们要从最后出现的位置向前更新,具体为啥,自己类比01背包
代码
//By AcerMo
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define lowbit(x) x&(-x)
using namespace std;
const int M=100500;
int n,a[M],b[M];
int nxt[M][6],f[M];
inline void add(int p,int x)
{
for (int i=p;i<=n;i+=lowbit(i))
f[i]=max(f[i],x);
return ;
}
inline int get(int p)
{
int ans=0;
for (int i=p;i;i-=lowbit(i))
ans=max(ans,f[i]);
return ans;
}
signed main()
{
scanf("%d",&n);n*=5;
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int i=1;i<=n;i++) scanf("%d",&b[i]);
for (int i=1;i<=n;i++)
nxt[a[i]][++nxt[a[i]][0]]=i;
for (int i=1;i<=n;i++)
for (int k=5;k>=1;k--)
{
int p=nxt[b[i]][k];
add(p,get(p-1)+1);
}
cout<<get(n);
return 0;
}