python 基础知识点(蓝桥杯python科目个人复习计划52)

今日复习内容:还是做题

例题1:四元组问题

问题描述:

从小学开始,小明就是一个非常喜欢数学的孩子。他喜欢用数学的方式解决各种问题。在他的高中时期,他遇到了一个非常有趣的问题,那就算给定一个长度为n的整数数组nums,判断是否存在四个不同的下标a,b,c,d,使得a < b < c < d,并且nums[d] < nums[c] < nums[a] < nums[b]。

小明非常喜欢这个问题,他决定用数学的方式来解决它。他首先想到了一个非常简单的方法,那就是暴力枚举。他用四个循环来枚举所有可能的下标组合,然后判断是否满足条件。但是这个方法非常耗时,当n很大时,计算量会非常大。

所以请求你给出一个快速智慧的方法。

输入格式:

输入仅两行,第一行包含一个整数n,第二行包含n个整数,其含义如上所述。

输出格式:

输出仅一行,包含一个字符串,YES表示题目存在上述描述的情况,否则输出NO。

参考答案:

n = int(input())
li = list(map(int,input().split()))
a = -math.inf
stack = []
min_r = [math.inf] * n
for i in range(n - 2,-1,-1):
    min_r[i] = min(min_r[i + 1],li[i + 1])
flag = False
for i in range(n):
    if li[i] < a and li[i] > min_r[i]:
        print('YES')
        flag = True
        break
    while stack and li[i] > stack[-1]:
        a = max(a,stack[-1])
        stack.pop()
    stack.append(li[i])
if not flag:
    print('NO')

运行结果:

以下是我对此题的理解:

这个问题要求判断是否存在四个不同的下标a,b,c,d,满足条件a < b < c < d,并且对应的数组元素满足nums[d] < nums[c] < nums[a] < nums[b]。换句话说,要找到数组中的四个元素,它们的大小顺序满足给定的条件。

对于解决这个问题的思路,我们可以尝试优化暴力枚举的方法,通过观察可以发现,我们需要维护一些关键的信息来进行判断。具体思路如下:

1维护一个递减的栈,栈中存放的是数组元素,用于寻找满足条件的a,b,c,d;

2.维护一个变量a,表示在当前位置之前的最大值,用于判断nums[a] < nums[b]的条件。

3.维护一个数组min_r,记录从当前位置开始到数组末尾的最小值,用于判断nums[d] < nums[c]的条件

n = int(input()):读取整数n,表示数组的长度

li = list(map(int,input().split())):读取一行整数,表示数组nums

a = -math.inf:初始化变量a,表示当前位置之前的最大值,初始值为负无穷

在这段代码中,变量a用来表示当前位置之前的最大值。初始将其设置为负无穷是为了确保在数组a中的初始值比任何数组元素都要小,这样可以保证在后续的变量中,a的值能够被正确更新为当前位置之前的最大值。这种设置可以保证a在后续的比较中能够正确地表示当前位置之前的最大值,保证算法的正确性。

stack = []:初始化一个空栈,用于维护递减序列

min_r = [math.inf] * n:初始化数组min_r,用于记录从当前位置开始到数组末尾的最小值,初始值为正无穷

在这段代码中,数组min_r被用来记录从当前位置开始到数组末尾的最小值。初始将其设置为正无穷是为了确保在后续的遍历中,min_r的初始值比任何数组元素都要大。这样可以保证在后续的遍历中,min_r能够正确更新为当前位置之后的最小值,这种设置可以保证min_r在后续的比较中能够正确地表示当前位置之后的最小值,保证算法的正确性。

for i in range(n - 2,-1,-1):遍历的起始位置是n-2,即倒数第二个位置,因为在更新min_r[i]时,需要用到li[i + 1]和min_r[i + 1],即当前位置的下一个位置的值,所有遍历的位置选择倒数第二个位置,是为了确保在更新min_r数组时,能够正确的利用到每个位置后面的元素信息。遍历的结束位置是-1,这是因为要遍历到数组的第一个位置,步长为-1,从后往前。以这种方式进行遍历可以确保在更新min_r时,每个位置的值都是其后所有元素的最小值,保证min_r的正确性。

flag = False:初始化标志位flag,表示是否找到满足条件的4个下标

for i in range(n):遍历数组元素

if li[i] < a and li[i] > min_r[i]:判断是否存在满足条件的4个下标

如果满足条件,则输出‘YES’,设置flag为True,并跳出循环

while stack and li[i] > stack[-1]:当栈不为空且当前元素大于栈顶元素时,执行以下操作:

a = max(a,stack[-1]):更新a为当前元素和栈顶元素的最大值

stack.pop():弹出栈顶元素

stack.append(li[i]):将当前元素压入栈中

if not flag:print('NO'):如果没有找到满足条件的四个下标,则输出NO

这段代码通过维护一个递减的栈和一个记录最小值的数组,以及一个变量记录最大值,来判断是否存在满足条件的4个下标,从而判断是否存在满足条件的4个元素。

标志位flag被用来表示是否找到满足条件的4个下标,初始将其设置为False,是为了在遍历整个数组后,如果没有找到满足条件的4个下标,就能够根据flag的值来判断并输出结果。如果在遍历过程中找到了满足条件的4个下标,则会将flag设置为True,而如果遍历完成后flag仍然为False,就直接输出‘NO’。因此将flag设置为False,是为了在后续的遍历中能够正确地判断是否找到了满足条件的4个下标,从而输出相应的结果。


例题2:肖恩的投球游戏

问题描述:

小羊肖恩最近迷上了投球游戏,具体来说,在他面前摆放了n个球筐,第i个框开始有ai个球。

接下来小羊会进行q次操作,每次操作会给出3个整数l,r,c,会将第l个框到第r个框,都投入c个球,请你输出操作完成之后每个框各有多少个球。

输入格式:

第一行输入两个整数n和q,表示球筐个数和操作次数

第二行输入n个整数,表示每个球筐最开始的球数

接下来q行,每行输入3个整数l,r,c

数据范围保证:1 <= n,q <= 10^5,1 <= l <= r <= n,1 <= ai,c <= 10^5

输出格式:

输出一行n个整数,表示每个框最终的球的个数,以空格分开。

参考答案:

n,q = map(int,input().split())
li = list(map(int,input().split()))
# diff = [0] * n
# diff[0] = li[0]
# for i in range(1,n):
#     diff[i] = li[i] - li[i - 1]
# print(*diff)
# 求差分数组
diff = [0] * (n + 1)
for i in range(n):
    diff[i] += li[i]
    diff[i + 1] -= li[i]
for i in range(q):
    l,r,c = map(int,input().split())
    l -= 1
    r -= 1
    diff[l] += c
    diff[r + 1] -= c
# 求前缀和
s = [0]
for i in range(n):
    s.append(s[-1] + diff[i])
print(*s[1:])

运行结果:

 

以下是我对此题的理解:

1.输入部分

首先从输入中获取球筐的数量n和操作次数q

接着获取一个长度为n的列表li,表示每个球筐初始的球数。

2.构建差分数组

差分数组diff的长度为n + 1,是为了方便处理边界情况

遍历初始球数列表li,将每个球筐的球数加到对应的差分数组位置上,并将下一个位置减去同样的球数,以便后续计算前缀和。

3.处理操作

对于每次操作,从输入中获取操作的起始球筐索引1,结束球筐索引r和投入的球数c

由于题目中球筐的编号是从1开始的,但代码中使用了从0开始的索引,所以需要将l和r都减去1

对差分数组进行更新,将起始球筐位置l加上投入的球数c,结束球筐位置r + 1减去投入的球数c,这样,差分数组记录了每个球筐的变化量。

4.计算前缀和

计算一个长度为n + 1的前缀和数组s,用于存储差分数组的前缀和

遍历差分数组diff,依次累积求和,得到前缀和数组s

5.输出结果

输出前缀和数组s的第一个元素到最后一个元素,即为每个球筐最终的球数。


例题3:泡澡

问题描述:

在一个寒冷的冬天,有N个人想要去澡堂泡澡,第i个人会在时间段[Si,Ti](不包括Ti)内每分钟使用Pi升热水。由于该澡堂设备简陋,无法 存储热水。热水器在每分钟最多能提供W升热水,现在请问该澡堂该澡堂能否满足这N个人的泡澡要求,如果可以请输出‘YES’,否则输出'NO'。

输入格式:

第一行包含两个整数N和W,表示洗澡的人数和热水器的容量。

接下来N行,每行包含3个整数Si,Ti,Pi(0 <= Si < Ti <= 2 * 10^5 ,1 <= W ,Pi <= 10^9),表示第i个人的洗澡计划。其中Si和Ti表示计划的开始时间和结束时间,Pi表示每分钟需要的热水量。

输出格式:

如果可以按照所有人的计划供应热水,则输出'YES',否则输出‘NO’。

参考答案:

​
n,w = map(int,input().split())
N = 200010
a = [0] * N
diff = [0] * N
for i in range(n):
    s,t,p = map(int,input().split())
    diff[s] += p
    diff[t] -= p
a[0] = diff[0]
for i in range(1,N):
    a[i] = a[i - 1] + diff[i]
if max(a) <= w:
    print('Yes')
else:
    print('No')

​

运行结果:

 

以下是我对此题的理解:

首先输入洗澡的人数n和热水器的容量w,并初始化一个足够大的数组N和两个长度为N的数组a和diff。

对于每个人的洗澡计划,从输入中获取开始时间s,结束时间t和每分钟需要的热水量p

在差分数组diff中,将开始时间s对应的位置加上每分钟需要的热水量p,将结束时间t对应的位置减去每分钟需要的热水量p。这样,差分数组记录了每个时间点热水的变化量。

然后通过差分数组diff计算出数组a,其中a[i]表示第i分钟澡堂内的总热水量,这里使用了差分数组的前缀和思想。

判断数组a中的最大值是否小于等于热水器容量w,如果是,则说明可以按照所有人的计划供应热水,输出'Yes',否则输出'No‘

这段代码利用了差分数组和前缀和的思想,以及对时间段内热水量的变化进行记录,从而得出判断结果。


例题4:肖恩的投球游戏加强版

问题描述:

小羊肖恩最近喜欢上了投球游戏,但他已经不满足只有一行球筐的玩法了。

具体来说,在他面前摆放了n * m个球筐,这些球筐形成了一个n * m的矩阵,整数ai,j表示第i行第j列的球筐最开始的球的个数。

接下来小羊会进行q次操作,每次操作会给出5个整数x1,x2,y1,y2,c,他将会以(x1,y1)为左上角,(x2,y2)为右下角的球筐矩阵都投入c个球。请你输出操作完成之后每个球筐各含有多少个球。

输入格式:

第一行输入3个整数n,m,q,表示球筐矩阵的大小和操作次数

接下来n行,每行包含m个整数,表示球筐矩阵

接下来q行,每次输入5个整数x1,x2,y1,y2,c。

数据范围保证:

1 <= q <= 10^5,1 <= n,m <= 10^3,1 <= x1 <= x2 <= n,1 <= y1 <= y2 <= m,1 <= ai,j, c  <= 10^5。

输出格式:

输出n行,每行m个数,表示操作完毕后每个球筐里球的个数。

参考答案:

n,m,q = map(int,input().split())
diff = [[0 for i in range(m + 2)]for j in range(n + 2)]
def pro(x1,y1,x2,y2,c):
    diff[x1][y1] += c
    diff[x1][y2 + 1] -= c
    diff[x2 + 1][y1] -= c
    diff[x2 + 1][y2 + 1] += c
for i in range(1,n + 1):
    tmp = [0] + list(map(int,input().split()))
    for j in range(1,m + 1):
        pro(i,j,i,j,tmp[j])
for i in range(q):
    x1,y1,x2,y2,c = map(int,input().split())
    pro(x1,y1,x2,y2,c)
for i in range(1,n + 1):
    for j in range(1,m + 1):
        diff[i][j] += diff[i - 1][j] + diff[i][j - 1] - diff[i - 1][j - 1]
    print(*diff[i][1:-1])

运行结果:

 

以下是我对此题的理解:

1.输入处理

从输入中获取球筐矩阵的大小n,m和操作次数q

初始化一个二维差分数组diff,大小为(n + 2)*(m + 2),并全部初始化为0

2.投球操作函数pro

pro函数用于处理每次投球操作,接受左上角坐标(x1,y1),右下角坐标(x2,y2)以及投入的球数c

在差分数组diff中更新四个角的值,使得这个矩形区域内的元素加上或 减去相应的投球数。这样,差分数组记录了每个球筐矩形区域内的球数变化。

3.初始化球筐矩阵

通过两层循环,依次读取每个球筐的初始球数,并调用pro函数更新差分数组,这样差分数组就记录了初始时每个球筐的球数。

4.处理投球操作

通过循环读取每次的投球操作,调用pro函数更新差分数组,这一步模拟了小羊进行投球操作的过程。

5.计算前缀和

通过两层循环,计算差分数组的前缀和,得到最终每个球筐的球数。


OK,我今天要做的题还有很多,但是有点费时间,所以我写到了下一篇。

那这篇就这样了,下一篇继续!

  • 46
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值