我正在尝试在一个拼接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
答案 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:原谅我糟糕的蟒蛇。