$Description$
求两个序列的最长公共上升子序列
$Solution$
$f[i][j]$表示$a$序列匹配到$i$和$b$序列匹配到$j$的最长上升序列的长度,这里并不要求$a[i]==b[j]$。
两层循环,外层$i=1...n1$,内层$j=1...n2$
转移:
$f[i][j]=max(f[i-1][1...j-1](if b[j]<a[i]))+1$
这里的$max(f[i-1][i...j-1](if b[j]<a[i]))$不用每次单独枚举,只要在循环内即使更新就可以了
或者,也可以用树状数组来维护.
$Code$

#include<bits/stdc++.h> #define Ri register int #define il inline #define go(i,a,b) for(Ri i=a;i<=b;++i) #define yes(i,a,b) for(Ri i=a;i>=b;--i) #define e(i,u) for(Ri i=b[u];i;i=a[i].nt) #define ll long long #define db double using namespace std; il int read() { Ri x=0,y=1;char c=getchar(); while(c<'0' || c>'9'){if(c=='-')y=-1;c=getchar();} while(c>='0' && c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();} return x*y; } const int N=2010; int n,m,a[N],b[N],f[N][N],as,d[N],t[N][N*4]; struct nd{int d,p;}c[N]; il bool cmp(nd x,nd y){return x.d<y.d;} il int lowbit(Ri x){return x&(-x);} il void change(Ri i,Ri j,Ri dat) { while(i<=n) { t[j][i]=max(t[j][i],dat); i+=lowbit(i); } } il int sum(Ri i,Ri j) { Ri ret=0; while(i>0) { ret=max(ret,t[j][i]); i-=lowbit(i); } return ret; } int main() { freopen("lcis.in","r",stdin); freopen("lcis.out","w",stdout); n=read(),m=read(); go(i,1,n)a[i]=read(),c[i]=(nd){a[i],i}; go(i,1,m)b[i]=read(); sort(c+1,c+n+1,cmp); go(i,1,n) if(i>=2 && c[i].d==c[i-1].d)d[c[i].p]=d[c[i-1].p]; else d[c[i].p]=i; go(i,1,n) { go(j,1,m) { f[i][j]=max(f[i][j],f[i][j-1]); if(a[i]==b[j]) f[i][j]=max(f[i][j],sum(d[i]-1,j-1)+1); } go(j,1,m)change(d[i],j,f[i][j]); } go(i,1,n)as=max(as,f[i][m]); printf("%d ",as); return 0; }

1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define Rg register 5 #define il inline 6 #define db double 7 #define ll long long 8 #define mem(a,b) memset(a,b,sizeof(a)); 9 #define go(i,a,b) for(Rg int i=a;i<=b;i++) 10 #define yes(i,a,b) for(Rg int i=a;i>=b;i--) 11 using namespace std; 12 il int read() 13 { 14 int x=0,y=1;char c=getchar(); 15 while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();} 16 while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();} 17 return x*y; 18 } 19 const int N=501; 20 int T,n1,n2,ans,a[N],b[N],al[N],f[N][N],lst[N][N]; 21 il void sol() 22 { 23 ans=0;mem(f,0);int x=n1,y=0,t; 24 go(i,1,n1) 25 { 26 t=0; 27 go(j,1,n2) 28 { 29 if(a[i]!=b[j])f[i][j]=f[i-1][j]; 30 if(a[i]>b[j]&&f[i][j]>f[i][t])t=j; 31 if(a[i]==b[j])f[i][j]=f[i][t]+1,lst[i][j]=t; 32 //cout<<"f["<<i<<"]["<<j<<"]:"<<f[i][j]<<endl; 33 } 34 } 35 go(i,1,n2)if(f[n1][i]>ans)ans=f[n1][i],y=i; 36 t=0; 37 while(f[x][y]) 38 { 39 while(a[x]!=b[y]){x--;if(!x)return;} 40 al[ans-t]=b[y],y=lst[x][y],t++; 41 } 42 } 43 int main() 44 { 45 T=read(); 46 while(T--) 47 { 48 n1=read();go(i,1,n1)a[i]=read(); 49 n2=read();go(i,1,n2)b[i]=read(); 50 sol(); 51 printf("%d ",ans); 52 if(ans){go(i,1,ans)printf("%d ",al[i]);printf(" ");} 53 } 54 return 0; 55 }