USACO 4.3 buylow

求最长下降子序列,平方的算法就可以过

第二问要求这些子序列的个数,相同的序列不可重复算,也是类似第一个问题的动态规划解法,但要处理重复。

 

这里注意到一个性质,如果对于两个相同的数,如A[i]和A[j](i<j,),如果以他们结尾的最长下降序列大小相同, 那么在i和j之间一定不存在异于A[i]的数A[k](i<k<j),使得以A[k]结尾的最长下降序列和以A[i]结尾的最长下降序列相同。由反证法很容易证明。

由此,我们可以得到一个算法,每次只处理相同数最右边的一个,具体参考实现的22~30行。另外,此题要用高精度,万恶题。。。

 

  1. int main()
  2. {
  3.     int i, j, k;
  4.    
  5.     freopen("buylow.in""r", stdin);
  6.     freopen("buylow.out""w", stdout);
  7.     
  8.     scanf("%d",&n);
  9.     for(i = 1; i <= n; i++) scanf("%d",&a[i]);
  10.     
  11.     a[0] = INT_MAX;
  12.     
  13.     int best = 1; d[1] = 1;
  14.     for(i = 2; i <= n; i++){
  15.         d[i] = 1;
  16.         for(j = 1; j < i; j++)
  17.             if(a[j] > a[i]) d[i] = max(d[i], d[j] + 1);
  18.         best = max(best, d[i]);
  19.     }
  20.     
  21.     cnt[1] = 1;
  22.     for(i = 2; i <= n; i++){
  23.         int last = -1;
  24.         if(d[i] == 1) { cnt[i] = 1; continue;}
  25.         for(j = i - 1; j >= 1; j--)
  26.         {
  27.             if(d[j] == d[i]-1 && a[j] > a[i] && a[j] != last){
  28.                 cnt[i] += cnt[j];
  29.                 last = a[j];
  30.             }
  31.         }
  32.     }
  33.     
  34.     BigInt ret = 0;
  35.     int last = -1;
  36.     for(i = n; i >= 1; i--)
  37.     {
  38.         if(d[i] == best && a[i] != last)
  39.         {
  40.             ret += cnt[i];
  41.             last = a[i];
  42.         }
  43.     }
  44.     
  45.     cout << best << " " << ret << endl;
  46.     scanf("%d",&n);
  47. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值