BestCoder Round #13 1003(单调性DP)HDU5064

Find Sequence

Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 68    Accepted Submission(s): 12


Problem Description
Give you an positive integer sequence  a1,a2,,ai,,an , and they satisfy  a1+a2++ai++an=M(0<M222) .
We can find new sequence  b1=aid1,b2=aid2,,bx=aidx,,by=aidy,,bt=aidt , where if x != y then  idx!=idy . and this sequence satisfy:
(1)  b1b2bt  
(2)  b2b1b3b2btbt1
We can find many sequences  b1,b2,b3,,bt . But we only want to know maximum t.
 

Input
The first line in the input file is an Integer  T(1T30) .
The first line of each test case contains two integer  n,M(0<M222) .
Then a line have n integer, they represent  a1,a2,,ai,,an .
 

Output
For each test case, output the maximum t.
 

Sample Input
   
   
2 6 19 3 2 1 3 4 6 1 4194304 4194304
 

Sample Output
   
   
5 1
Hint
For the first testcase, The Sequence is 1 2 3 4 6

题意:RT

思路:首先排序是肯定的,然后无论怎么选条件1始终满足

            现在看条件2,因为条件2还跟前后的差值有关

            那么就要考虑DP了
       
            用DP[i][j]表示以第i和第j个数结尾的最长子序列

            那么转移方程为DP[i][j]=max(DP[k][i]) + 1,其中j>i ,i>=k

            这样暴力算是n^3的复杂度,显然会超时

            注意这是有个单调性的,DP[i][j]满足的最优值一定DP[i][j+1]也可以取,所以在j增大的时候,k不必重新从i开始递减(因为这段重复的区间之前已经算过了)

            k只需要继续以前的位置递减即可,保存最优值,然后赋给dp[i][j]

#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
         #include 
        
          #include 
          #include 
          
            #include 
           
             #include 
            
              using namespace std; #define lson l,m,o<<1 #define rson m+1,r,o<<1|1 const int MAXN = 4200000; int a[MAXN]; int b[MAXN]; int dp[2010][2010]; int main() { int t; scanf("%d",&t); while(t--){ int n,m; scanf("%d%d",&n,&m); memset(a,0,sizeof(a)); for(int i=1;i<=n;i++){ int x; scanf("%d",&x); a[x]++; } int cnt=0; for(int i=1;i<=m;i++){ if(a[i])b[++cnt]=i; } memset(dp,0,sizeof(dp)); int ans=0; for(int i=1;i<=cnt;i++){ dp[i][i]=a[b[i]]; ans=max(ans,dp[i][i]); } for(int i=1;i<=cnt;i++){ int k=i; int temp=dp[i][i]; for(int j=i+1;j<=cnt;j++){ for(;k && b[i]-b[k]<=b[j]-b[i];k--){ temp=max(temp,dp[k][i]+1); } dp[i][j]=temp; ans=max(ans,temp); } } printf("%d\n",ans); } return 0; } 
             
            
           
         
       
      
      
     
     
    
    
   
   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值