太久没有刷算法题了,前四道题居然直接干到50分钟去了... em.... 得好好练习了.....
题目不全,后续再补。。。
简述:给一个数组,自由将数组分成n个子数组,每个子数组都会最大最小值,分别将其差累加后,只要满足累加值最大化就好了。
思路:排个序,只要当前ls中还有数据且长度不为1,就从最左边和最右边各取一个相加,类似于双端队列,pyyyds~。
def solve():
n = int(input())
ls = list(map(int,input().split()))
ls.sort(reverse = True)
res = 0
while ls:
if len(ls) == 1:
break
max_ = ls.pop(0)
min_ = ls.pop(-1)
res += max_ - min_
print(res)
def main():
t = int(input())
while t:
solve()
t -= 1
main()
简述:给一个数组,你可以有若干次或者零次操作,在这每次操作中,你可以任选一个区间(l,r)(1<=l<=r<=n),使得数组中的这个区间内所有的元素都乘-1,最后问求最少操作次数以及这个数组的最大累积和。
思路:这个数组最大累积和必然是这个数组中的所有元素的绝对值之和。而目标是使用尽可能少的操作数让数组中的多个负数一次性变成正数,即尽可能的让每个[l,r]的覆盖范围更大。这里用到了双指针,左指针从左往右找到数组中第一个小于0的数,对于确定的左指针 l ,更新最大的右指针r,使得数组[l,r]内都是小于等于0的数,以便一次性解决,直到 r 无法继续右移,则 l 的新位置更新为r+1,此时只需线性复杂度就可以找到最少的操作次数了。
def solve():
n = int(input())
ls = list(map(int,input().split()))
sums = 0
for l in ls:
sums += abs(l)
l, cnt = 0, 0
while l < n:
if ls[l] < 0:
cnt += 1
r = l
while r < n - 1 and ls[r + 1] <= 0: r += 1
l = r + 1
else:
l += 1
print(sums,cnt)
def main():
t = int(input())
while t:
solve()
t -= 1
main()
简述:有一颗无穷大的树,给一个结点n,问从结点n到根节点(结点1)路径上的结点之和为多少?
思路:dfs写就可以了,主要还是公式,编号 i 结点的两个孩子结点编号分别为 2i 和 2i + 1,定义一个dfs状态,参数表示当前结点编号,每次都往父节点递归即可,边界条件为遇到根节点时返回,每次递归都将结点值记录起来就是答案了。
res = 0
def dfs(ver):
global res
res += ver
if ver == 1:
return
if ver % 2 == 0:
dfs(ver // 2)
else:
dfs((ver - 1) // 2)
def main():
global res
t = int(input())
for _ in range(t):
n = int(input())
dfs(n)
print(res)
res = 0
main()
代码为比赛代码, 文章写得粗糙,题目暂不完整,后续补全和优化,请海涵!