2014-10-15 22:36:29
思路:挺好的一道动规题,需要仔细分析。怒粘一篇std题解。
1003 Find Sequence
首先考虑解的结构一定是C1,C1,…,C1,C2,C3,…,Cm这种形式,其中满足C1<C2<C3<…<Cm
所以对a1,a2,a3,…,an去重后从小到大排序得到c1,c2,c3,…,cx其中x是sqrt(M)级别的,用DP[i][j]表示以ci和cj结尾的满足条件的最长序列 首先初值化 DP[i][i]=count(ci) 即ci在原序列中的个数。 而dp[i][j]=max(dp[k][i] 其中k≤i还满足ci−ck≤cj−ci)+1 这样的复杂度是 O(x^3),在题中x最大为1000级别所以会超时,要使用下面优化 因为 dp[i][j]=max(dp[k][i] 其中k≤i还满足ci−ck≤cj−ci)+1 dp[i][j+1]=max(dp[k][i] 其中k≤i还满足ci−ck≤cj+1−ci)+1 注意到cj+1>cj 所以满足ci−ck≤cj−ci的dp[k][i]必然满足ci−ck≤cj+1−ci因而不必重复计算 即最后复杂度可以为O(x^2).
1 /************************************************************************* 2 > File Name: 1003.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Sat 11 Oct 2014 08:42:37 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <queue> 16 #include <iostream> 17 #include <algorithm> 18 using namespace std; 19 #define lp (p << 1) 20 #define rp (p << 1|1) 21 #define getmid(l,r) (l + (r - l) / 2) 22 #define MP(a,b) make_pair(a,b) 23 typedef long long ll; 24 const int INF = 1 << 30; 25 const int maxn = 1 << 12; 26 27 int val[1 << 22],c[maxn],n,m,t; 28 int dp[maxn][maxn]; 29 30 int main(){ 31 scanf("%d",&t); 32 while(t--){ 33 memset(dp,0,sizeof(dp)); 34 scanf("%d%d",&n,&m); 35 for(int i = 1; i <= n; ++i) scanf("%d",&val[i]); 36 sort(val + 1,val + n + 1); 37 int cur = 1; 38 c[cur] = 1; 39 for(int i = 2; i <= n; ++i){ 40 if(val[i] == val[cur]) ++c[cur]; 41 else{ 42 val[++cur] = val[i]; 43 c[cur] = 1; 44 } 45 } 46 int ans = 0; 47 for(int i = 1; i <= cur; ++i) dp[i][i] = c[i]; 48 for(int i = 1; i <= cur; ++i){ 49 int k = i,tmax; 50 tmax = dp[i][i]; 51 ans = max(ans,tmax); 52 for(int j = i + 1; j <= cur; ++j){ 53 for(; k > 0 && val[i] - val[k] <= val[j] - val[i]; --k){ 54 tmax = max(tmax,dp[k][i] + 1); 55 } 56 dp[i][j] = tmax; 57 ans = max(ans,tmax); 58 } 59 } 60 printf("%d\n",ans); 61 } 62 return 0; 63 }