Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 长度k的递增子序列数_C++_Algorithm_Lis_Fenwick Tree - Fatal编程技术网

C++ 长度k的递增子序列数

C++ 长度k的递增子序列数,c++,algorithm,lis,fenwick-tree,C++,Algorithm,Lis,Fenwick Tree,我试图理解一种算法,该算法给出了数组中长度K在时间O(nklog(n))内递增的子序列的数目。我知道如何使用O(k*n^2)算法来解决同样的问题。我查了一下,发现这个解决方案使用了BIT(Fenwick树)和DP。我还发现了一些代码,但我一直无法理解它 以下是我访问过的一些有用的链接 如果有人能帮助我理解这个算法,我将不胜感激。我正在复制我的算法,其逻辑解释如下: dp[i, j] = same as before num[i] = how many subsequences that

我试图理解一种算法,该算法给出了数组中长度K在时间O(nklog(n))内递增的子序列的数目。我知道如何使用O(k*n^2)算法来解决同样的问题。我查了一下,发现这个解决方案使用了BIT(Fenwick树)和DP。我还发现了一些代码,但我一直无法理解它

以下是我访问过的一些有用的链接




如果有人能帮助我理解这个算法,我将不胜感激。

我正在复制我的算法,其逻辑解释如下:

dp[i, j] = same as before num[i] = how many subsequences that end with i (element, not index this time) 
         have a certain length

for i = 1 to n do   dp[i, 1] = 1

for p = 2 to k do // for each length this time   num = {0}

  for i = 2 to n do
    // note: dp[1, p > 1] = 0 

    // how many that end with the previous element
    // have length p - 1
    num[ array[i - 1] ] += dp[i - 1, p - 1] *1*   

    // append the current element to all those smaller than it
    // that end an increasing subsequence of length p - 1,
    // creating an increasing subsequence of length p
    for j = 1 to array[i] - 1 do *2*       
      dp[i, p] += num[j]
您可以使用段树或二元索引树来优化
*1*
*2*
。这些将用于有效地处理
num
数组上的以下操作:

  • 给定
    (x,v)
    v
    添加到
    num[x]
    (与
    *1*
    相关)
  • 给定
    x
    ,求和
    num[1]+num[2]+…+num[x]
    (与
    *2*
    相关)
对于这两种数据结构来说,这些都是微不足道的问题

注意:这将具有复杂性
O(n*k*log S)
,其中
S
是数组中值的上限。这可能不够好,也可能不够好。要使其
O(n*k*logn)
,需要在运行上述算法之前规范化数组的值。规范化意味着将所有数组值转换为小于或等于
n
的值。因此:

5235 223 1000 40 40
变成:

4 2 3 1 1

这可以通过排序(保留原始索引)来实现。

注意显示您发现的具有O(nklog(n))复杂性的代码吗?topcoder链接现在已修复。你们可以在那个里找到它。不需要马上用BIT就可以更容易地思考这个问题。我在这里解释:我无法理解你的算法。你能在我的帖子中详细解释一下吗?也许能给我一个关于使用段树的想法,然后我会用BIT提出一个解决方案。提前谢谢,我补充了一些解释。如果您仍然无法理解它,请确切地告诉我有什么不清楚的地方,我会尽力帮助您。有些事情我还无法理解。该算法如何保证存储不断增加的子序列的数量。我知道DP O(nnk)是怎么做的,但是这个。。。不是clue@Andrés-基本上,您可以计算每个值在特定长度中的数量(不像经典DP中的索引)。可以将当前值附加到所有较小的值,获得+1长度。