📜  门| Sudo GATE 2021 测验 |第 32 题(1)

📅  最后修改于: 2023-12-03 15:42:20.392000             🧑  作者: Mango

Sudo GATE 2021 测验 | 第 32 题

本题主题是门,主要考察程序员的逻辑思维和编程能力。

题目描述

有 n 扇门,每扇门上都有一些铁钉。第 i 扇门上的铁钉数量为 ai。现在你将会进行 q 次操作,每次操作会选出一个数 k,并将第 i 到第 i+k-1 扇门上的铁钉数量翻倍,即每扇门上的铁钉数量变为原来的两倍。

请你在这些操作完成后计算最后一扇门上的铁钉数量。

输入格式

第一行一个整数 n,表示门的数量。

第二行 n 个整数,表示每扇门初始的铁钉数量 a1,a2,…,an。

接下来一行一个整数 q,表示操作的次数。

接下来 q 行,每行一个整数 ki,表示这次操作需要翻倍的扇门数量。

输出格式

一个整数,表示操作完成后最后一扇门上的铁钉数量。

数据范围

1≤n≤105 1≤ai≤105 1≤q≤105 1≤ki≤n

输入样例1
5
1 2 3 4 5
1
3
输出样例1
48
输入样例2
5
1 2 3 4 5
2
1
2
输出样例2
64
解题思路

我们可以使用树状数组进行处理。首先我们需要对每次操作的影响进行一下分析。

对于第 i 次操作,我们需要将第 1 到第 i+k-1 扇门上的铁钉数量翻倍,也就是将第 1 到第 i+k-1 扇门上的铁钉数量全部加上原来的值。这里可以用一个差分数组 diff 来存放,在更新第 i 到第 i+k-1 扇门时,只需要将 diff[i] 加上 a[i] 即可。

接下来的问题是如何快速计算最后一扇门上的铁钉数量。我们可以从后往前遍历 diff 数组,依次计算出每扇门最终的铁钉数量。

代码如下:

def solve():
    n = int(input())
    nums = list(map(int, input().split()))
    diff = [nums[i] - nums[i-1] for i in range(1, n)]
    q = int(input())
    for _ in range(q):
        k = int(input())
        diff[0] += nums[0]
        if k < n:
            diff[k] -= nums[0]
        nums[0] <<= 1
    for i in range(1, n):
        diff[i] += diff[i-1]
    print(nums[n-1] + diff[n-2])

代码中的 diff 数组就是差分数组,最后计算最后一扇门上的铁钉数量时,只需要将 nums[n-1] 加上 diff[n-2] 即可。