题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1264
因为每个字符至多出现5次,在A中记录下来。然后在B中扫一遍,因为a[i]=b[j]时f[i]++,所以维护一个树状数组记录最大值就可以了。
注意转移的顺序
#include<cstring> #include<iostream> #include<cstdio> #include<map> #include<cmath> #include<algorithm> #define rep(i,l,r) for (int i=l;i<=r;i++) #define down(i,l,r) for (int i=l;i>=r;i--) #define clr(x,y) memset(x,y,sizeof(x)) #define low(x) (x&(-x)) #define maxn 100500 #define inf 2000000000 #define mm 1000000007 using namespace std; int a[maxn][6],n,t[maxn],cnt[maxn],f[maxn]; int read(){ int x=0,f=1; char ch=getchar(); while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} return x*f; } void add(int x,int y){ while (x<=n){ t[x]=max(t[x],y); x+=low(x); } } int ask(int x){ int ans=0; while (x>0){ ans=max(ans,t[x]); x-=low(x); } return ans; } int main(){ int ans=0; n=read(); n=n*5; rep(i,1,n) { int x=read(); a[x][++cnt[x]]=i; } rep(i,1,n) { int x=read(); down(j,5,1) { int now=a[x][j]; f[now]=max(f[now],ask(now-1)+1); add(now,f[now]); ans=max(ans,f[now]); } } printf("%d ",ans); return 0; }