Python - 多次添加到列表拼接,优化,算法

时间:2014-12-31 00:17:33

标签: python algorithm list optimization splice

我正在尝试在一个拼接l [i:j(包含)]中向列表I的每个列表元素添加一个常量num_to_add,其中给出了许多形式为[i,j,num_to_add]的查询。

其中t的格式为[[i,j,num_to_add],[i,j,num_to_add]等] 我将t的每个元素添加到列表I中,它完全由零组成。

我目前的代码是这样的: 我遍历t,我的查询中的子列表,并将num_to_add添加到每个列表拼接元素。我输出列表I中小于整数n的元素数。

我如何从嵌套的for循环中优化它?这是针对可能适用于其他项目的一小部分问题。

编辑4: 样本输入:

4
1
3
1 3 1
2 3 2
3 3 2

编辑5: 完整代码:

I = [0] * int(input())
n = int(input())
j = int(input())
t = [list(map(int, input().split())) for i in range(j)]

tree = []
for i in range(1, 2*len(I)+1):
    tree.append([0,0])

def update(pos , left , right , i , j , val):

    ####updating segment tree to add value val in list l from index i to j

    i=max(i , left)
    j=min(j , right)
    if i > j:
       return

    if i==left and j==right:
       tree[pos][0] = tree[pos][0] + val*( j - i + 1 )
       tree[pos][1] = tree[pos][1] + val
       return

    mid = (left + right)/2

    ### the range breaks down into two parts left to mid and mid+1 to right 
    ### at positions 2*pos and 2*pos+1 in tree respectively

    update(2*pos , left , mid , i , j , val)
    update(2*pos + 1 , mid+1 , right , i , j , val) 
    tree[pos][0] = tree[2*pos][0] + tree[2*pos + 1][0] + tree[pos][1]*(right - left +1 ) 


def getvalue(pos , left , right , i , j ):

    ###gets sum of elements in list from index i to j in our case
    ### i will be equal to j , will see below 

    i = max(i , left)
    j=  min(j , right)
    if i > j:
        return 0
    if i==left and j==right:
        return tree[pos][0]

    mid = (left + right)/2 
    return getvalue(2*pos , left , mid , i , j) + getvalue(2*pos+1 , mid+1 , right , i , j) + tree[pos][1]*(j - i + 1)

###Remember l is 1 based indexed
for i in range( len(t) ):
    update(1 , 1 , len(I) , t[i][0] , t[i][1] , t[i][2])

ans = 0

###Remember l is 1 based indexed
for i in range(1 , len(I)+1):
   ###see we only use getvalue where i and j parameters of getvalue are same
   value = getvalue(1 , 1 , len(I) , i , i) 
   if value < n:
       ans = ans + 1

print(ans)

错误:

Traceback (most recent call last):
  File, line 58, in <module>
    value = getvalue(1 , 1 , len(I) , i , i)
# A lot of these:
  File "/home/max3/Documents/Python/DMOJ TCE Battle Positions.py", line 47, in getvalue
    return getvalue(2*pos , left , mid , i , j) + getvalue(2*pos+1 , mid+1 , right , i , j) + tree[pos][1]*(j - i + 1)
# And one of this.
  File "/home/max3/Documents/Python/DMOJ TCE Battle Positions.py", line 44, in getvalue
    return tree[pos][0]
IndexError: list index out of range

1 个答案:

答案 0 :(得分:1)

细分树使您能够在 O(logN)中更新和检索列表中元素的总和,其中 N 是列表的大小。查找并说服自己细分树的工作原理 Segment Tree
(另一个列表)成为段树,它是列表 l 的两倍,并且它的每个元素都是另一个大小为2的列表,初始化为零。 (我将 l 作为基于1的索引)。这适用于所有 i 从1到 2N < / strong> 树[i] = [0,0] tree [i] [0] 是此索引对应的范围的总和,以及 tree [i] [1] 更新时添加到此范围的值。例如树[1] [0] 存储范围1到 N 的元素总和。

I = [0] * int(input())
n = int(input())
j = int(input())
t=[] 
tree=[]
for i in range(j):
   s=raw_input()
   l=s.split()
   for x in range(len(l)):
       l[x]=int(l[x])
   t.append(l)

for i in range(1,2*len(I)+1):
   tree.append([0,0])

def update(pos , left , right , i , j , val):

    ####updating segment tree to add value val in list l from index i to j

    i=max(i , left)
    j=min(j , right)
    if i > j:
       return

    if i==left and j==right:
       tree[pos][0] = tree[pos][0] + val*( j - i + 1 )
       tree[pos][1] = tree[pos][1] + val
       return

    mid = (left + right)/2

    ### the range breaks down into two parts left to mid and mid+1 to right 
    ### at positions 2*pos and 2*pos+1 in tree respectively

    update(2*pos , left , mid , i , j , val)
    update(2*pos + 1 , mid+1 , right , i , j , val) 
    tree[pos][0] = tree[2*pos][0] + tree[2*pos + 1][0] + tree[pos][1]*(right - left +1 ) 


def getvalue(pos , left , right , i , j ):

    ###gets sum of elements in list from index i to j in our case
    ### i will be equal to j , will see below 

    i = max(i , left)
    j=  min(j , right)
    if i > j:
        return 0
    if i==left and j==right:
        return tree[pos][0]

    mid = (left + right)/2 
    return getvalue(2*pos , left , mid , i , j) + getvalue(2*pos+1 , mid+1 , right , i , j) + tree[pos][1]*(j - i + 1)

现在您的分段树已准备好,我们处理查询,我们只计算数量 小于某个值的元素 n

for i in range( len(t) ):
    update(1 , 1 , N , t[i][0] , t[i][1] , t[i][2])

ans = 0

###Remember l is 1 based indexed
for i in range(1 , N+1):
   ###see we only use getvalue where i and j parameters of getvalue are same
   value = getvalue(1 , 1 , N , i , i) 
   if value < n:
       ans = ans + 1

print ans

与您的相比,此算法的所有复杂性都是 O((t)* logN + N的大小) 在最坏的情况下,它将是 O((t)* N的大小)。此外,查询是范围更新我 已懒惰更新(谷歌懒惰传播),以便更新和查询一次保持 的 O(logN)的

PS:原谅我糟糕的蟒蛇。