题目描述
小明是个鹅卵石收藏者,从小到大他一共收藏了 nn 块鹅卵石,编号分别为 1\sim n1∼n,价值分别为 a_1,a_2,\cdots , a_na1,a2,⋯,an。
这天他乘船准备去往蓝桥王国,然而天有不测风云,小明所在的海域下起了暴雨。
很快小明船上的积水越来越多,为了防止沉船,小明不得不选择若干块他收藏的鹅卵石丢弃。
小明制定了一套名为m计划
的选择方案,其内容如下:
- 对于任意区间 [i,i + m - 1][i,i+m−1]丢弃价值最小的鹅卵石i\in[1,n-m+1]i∈[1,n−m+1]。
- 对于一块鹅卵石,它在 mm 计划中是可以被丢弃多次的。
请你输出将被小明丢弃的鹅卵石的价值。
输入描述
输入第 11 行包含两个正整数 n,mn,m。
接下来一行包含 nn 个正整 a_1,a_2,\cdots,a_na1,a2,⋯,an,表示鹅卵石的价值。
1\leq m \leq n \leq 5\times 10^51≤m≤n≤5×105,0\leq a_i\leq 10^90≤ai≤109。
输出描述
输出共 n-m+1n−m+1 行,每行输出一个整数,第 ii 行输出整数的含义为 a_i,a_{i+1},\cdots,a_{i+m-1}ai,ai+1,⋯,ai+m−1 的最小值。
输入输出样例
示例 1
5 3
5 3 2 4 1
2
2
1
运行限制
- 最大运行时间:1s
- 最大运行内存: 256M
思路:
参考这一篇,都是求区间最值
https://blog.csdn.net/qq_51118755/article/details/122774237
我们这里只需要调整一下输出即可
代码
from math import *
n,m=map(int,input().split())
b=list(map(int,input().split()))
maxn=100001
a=[0]*maxn
for i in range(1,n+1):
a[i]=b[i-1]
#创建40列,maxn行的二维数组数组dp[x][y],并初始化
#dp[x][y]代表左端点是x,区间长度是2^k的区间最大值或者最小值
dp_min=[[0] * 40 for row in range(maxn)]
#从初始长度为1的小区间开始递推
for i in range(1,n+1):
dp_min[i][0]=int(a[i])
#求得区间长度的2的对数,目的是限制k的范围
#使得2^k<n,计算出以每一个以s为起点,区间为2^k的最值
p=int(log2(n))
for k in range(1,p+1):
for s in range(1,n+2-(1<<k)):
#后一个区间的最大值可以由覆盖此区间的前两个小区间确定
dp_min[s][k]=min(dp_min[s][k-1],dp_min[s+(1<<(k-1))][k-1])
for i in range(1,n-m+2):
#题目中已经给定了我们区间长度,直接使用即可
k=int(log2(m))
print(min(dp_min[i][k],dp_min[i+m-1-(1<<k)+1][k]))