传送门
http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=726&pid=1003
分析:这道题依然是动态规划,实际上是经典问题的变形,因为要求值必须连续,所以我们应该采取一些特殊的手段。
我们设f[i]表示f[i]为第一个序列中以高度i为结尾的最长连续递增子序列,使用g[i] 表示第二个序列的所以每读入一个数
所以我们有f[i] = f[i-1] + 1;g[i]类似
然后我们考虑统计答案,易得,ans = max{min{f[i],g[i]}}
因为要求的是公共子序列,所以不能选择两个序列中长的那个,也就是说,我们一定有较短的序列出现在另一个序列中。
所以我们就可以统计答案了。
1 #include <queue> 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 typedef long long ll; 8 inline void read(int &x){ 9 x=0;char ch;bool flag = false; 10 while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true; 11 while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x; 12 } 13 inline int cat_max(const int &a,const int &b){return a>b ? a:b;} 14 inline int cat_min(const int &a,const int &b){return a<b ? a:b;} 15 const int maxn = 100010; 16 const int maxnum = 2000010; 17 int f[maxnum],g[maxnum]; 18 int a[maxn],b[maxn]; 19 int main(){ 20 int T;read(T); 21 while(T--){ 22 int n,m;read(n);read(m); 23 for(int i=1;i<=n;++i){ 24 read(a[i]); 25 f[a[i]] = f[a[i]-1] + 1; 26 }int ans = 0; 27 for(int i=1;i<=m;++i){ 28 read(b[i]); 29 g[b[i]] = g[b[i]-1] + 1; 30 ans = cat_max(ans,cat_min(f[b[i]],g[b[i]])); 31 }printf("%d ",ans); 32 for(int i=1;i<=n;++i) f[a[i]] = 0; 33 for(int i=1;i<=m;++i) g[b[i]] = 0; 34 } 35 getchar();getchar(); 36 return 0; 37 }