📜  门|门CS 2011 |问题 37(1)

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

题目描述

南京大学的魏老师和孟老师玩一个传送门游戏。这个游戏的规则如下:有N个房间排成一排,第i个房间里面有Ai个人。有两个传送门,第一个传送门位于第L个房间,第二个传送门位于第R个房间。如果一个人在第L个房间或第R个房间内,他就可以通过传送门瞬间到达另一个传送门所在的房间里去。请问,经过一次瞬间传送,最多可以有多少个人在传送门所在的两个房间之间经过?

输入格式

第一行包含两个整数N和V,分别表示房间的数量和当前传送门所在的房间编号。

第二行包含N个整数,分别表示每个房间内的人数。

输出格式

仅一行,为最多有多少个人在两个传送门之间经过。

输入样例

4 2
1 2 3 4

输出样例

5

解题思路

此题是一道很经典的前缀和+滑动窗口问题。我们可以先求出前缀和数组$s$,表示$s[i]$为前$i$个房间内的总人数。

那么如果要求的区间为$[a, b]$,区间内总人数为$s[b]-s[a-1]$。

接着我们需要思考如何在$O(N)$时间复杂度内枚举所有区间。这个时候,我们可以使用滑动窗口技巧。

假设当前窗口左端点为$i$,右端点为$j$。那么如果当前区间和$s[j]-s[i-1]$比之前记录的最大值要大,那么更新最大值。

接着判断如果$j-i<V$,那么移动右端点$j+1$;反之,移动左端点$i+1$。

直至$i$和$j$都越过了数组边界,我们就可以得到答案。

代码实现

def max_people(rooms, v):
    n = len(rooms)
    s = [0] * (n + 1)

    for i in range(n):
        s[i+1] = s[i] + rooms[i]

    ans = 0
    i = j = 1
    while j <= n:
        if j - i < v:
            j += 1
        else:
            ans = max(ans, s[j]-s[i-1])
            i += 1

    return ans