$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][1...j-1](ifb[j]<a[i]))$不用每次单独枚举,只要在循环内即使更新就可以了
$Code$
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\n",ans); 52 if(ans){go(i,1,ans)printf("%d ",al[i]);printf("\n");} 53 } 54 return 0; 55 }