我已经连这种傻逼题都不会了orz
正常的dp是$O(n^2)$的,枚举第一个数组的$j$,然后第二个数组的$k$,如果相等,则$dp[i]=dp[j]+1$,否则$dp[i]=dp[j]$
然后发现可以用树状数组优化这个过程……
不知道讲清楚没有因为我自己都还有点懵
1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 using namespace std; 5 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 6 char buf[1<<21],*p1=buf,*p2=buf; 7 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} 8 int read(){ 9 #define num ch-‘0‘ 10 char ch;bool flag=0;int res; 11 while(!isdigit(ch=getc())) 12 (ch==‘-‘)&&(flag=true); 13 for(res=num;isdigit(ch=getc());res=res*10+num); 14 (flag)&&(res=-res); 15 #undef num 16 return res; 17 } 18 const int N=1e5+5; 19 int c[N],f[N][5],cnt[N],n; 20 inline void add(int x,int y){ 21 for(;x<=n;x+=x&-x) cmax(c[x],y); 22 } 23 int query(int x){ 24 int res=0;for(;x;x-=x&-x) cmax(res,c[x]);return res; 25 } 26 int main(){ 27 // freopen("testdata.in","r",stdin); 28 n=read()*5; 29 for(int i=1,x;i<=n;++i) 30 x=read(),f[x][cnt[x]++]=i; 31 for(int i=1;i<=n;++i){ 32 int x=read(); 33 for(int j=4;j>=0;--j){ 34 int at=f[x][j]; 35 add(at,query(at-1)+1); 36 } 37 } 38 printf("%d\n",query(n)); 39 return 0; 40 }
原文:https://www.cnblogs.com/bztMinamoto/p/9818771.html