• [topcoder]IncreasingSubsequences


    http://community.topcoder.com/stat?c=problem_statement&pm=7753&rd=10672

    http://community.topcoder.com/tc?module=Static&d1=match_editorials&d2=srm348

    这道题看着就是DP,但怎么DP呢?

    一开始按照测试例子{1,3,2,6,4,5}和答案{1,2,4,5}, {1,3,4,5}, {1,2,6} and {1,3,6}产生了错觉,以为必须要以该点结尾的最长子序列。
    写完之后比照正确答案调试许久,发现不对。{4,2,1,3,5}可以产生序列{1,3,5},{2,3,5}和{4,5}。但最后那个显然不是最长子序列。
    所以对照答案,正确的是,从左到右计算以a[i]结束的序列个数cnt[]。第a[i]个的和之前的a[j]有关,j从i-1往0回推,如果a[j]比a[i]小,那么(可能)要加上cnt[j]。但如果j和i中已经有数a[x]大于j了,就不算了,因为j可能在a[x]结尾的序列里算过了。
    所以用{4,2,1,3,5}举例,计算5的时候,会先算到3的cnt值是2,然后算到4的cnt值是1,那么5的cnt值是2+1==3。1不用往里考虑是因为1<3,肯定在以3结尾的子序列里了。

    那么计算最后的结果时,从后往前扫,如果后面已经有比现在的a[i]大的了,就不用再加了,肯定在它的序列里了。拿{1,3,2,6,4,5}举例,从后往前扫,5算完以后,4不用加了,肯定在5结尾的序列里,扫到6时,6大于之前的max 5,所以有个新的序列,要加上。

    import java.util.*;
    
    public class IncreasingSubsequences
    {
        public long count(int[] a)
        {
            ArrayList<Long> end = new ArrayList<Long>();
            end.add(1l);
            for (int i = 1; i < a.length; i++)
            {
                int shadow = 0;
                long sum = 0;
                for (int j = i-1; j >= 0; j--)
                {
                    if (a[j]>shadow && a[j] < a[i])
                    {
                        sum = sum + end.get(j);
                        shadow = a[j];
                    }
                }
                if (sum == 0) sum = 1;
                end.add(sum);
            }
            long ans = 0;
            int max = 0;
            for (int i = a.length -1; i >= 0; i--)
            {
                if (a[i] > max)
                {
                    ans = ans + end.get(i);
                    max = a[i];
                }
            }
            return ans;
        }
    }
    

      

  • 相关阅读:
    SQL
    第九章
    第三章 表单
    第二章 表格,列表,媒体元素
    HTML5基础
    Java第一本书总复习
    字符串
    人机猜拳
    类的无参方法
    类和对象
  • 原文地址:https://www.cnblogs.com/lautsie/p/3339981.html
Copyright © 2020-2023  润新知