蓝桥云--附近最小(RMQ问题一题多解)

原题目地址:附近最小


 一、朴素法方法

【基本思路】

        首先预处理出新数组new,它的含义是:new[i] = (a[i],i) ,并按a[i]值的大小进行排序。然后设置一个判断是否访问过的数组st[i],然后开始从小到大枚举new里面的每一个元素。在这里同爆搜无差别,小tips是当sum(st)==n时直接停止,可以省很多时间。不过蓝桥杯数据比较弱,能过,容易被一些极端数据hark掉。

【Python程序代码】

n = int(input())
a = list(map(int,input().split()))
k = int(input())
new = sorted([ (num,i) for i,num in enumerate(a) ] )
st = [0]*(n)
ans = [0]*(n)
for num,i in new:
  for j in range(max(0,i-k),min(n,i+k+1)):
    if st[j]==0:
      st[j]=1
      ans[j]=num
  if sum(st)==n:break
for i in range(n):
  print(ans[i],end=' ')

二、ST算法求解

【基本思路】

        ST算法是求解RMQ问题的高效算法,本题刚好撞上求解静态区间的最小值。因此直接打ST算法的板子秒了。(被卡了两个点,pypy卡1个点)。。。

【Python程序代码】

from math import *
n = int(input())
a = [0] + list(map(int,input().split()))
kk = int(input())
N = n+10
dp = [[0]*(40) for _ in range(N)]
def st_init():
    global dp
    for i in range(1,n+1):dp[i][0]=a[i]
    p = int(log2(n))
    for k in range(1,p+1):
        for s in range(1,n+2-(1<<k)):
            dp[s][k] = min(dp[s][k-1],dp[s+(1<<(k-1))][k-1])
def st_query(L,R):
    k = int(log2(R-L+1))
    return min(dp[L][k],dp[R-(1<<k)+1][k])
st_init()
for i in range(1,n+1):
    print( st_query(max(1,i-kk),min(n,i+kk)),end=' ')

三、单调队列求解

【基本思路】

        用列表模拟栈,预处理出一个new数组,含义是new[i] = (a[i],i),由于使用单调队列,所以还需要在列表的尾部添加k个极大值元素,然后调用单调队列的板子。秒了。

【Python程序代码】

from collections import *
n = int(input())
a = [0] + list(map(int,input().split()))
k = int(input())
new = [ (num,i) for i,num in enumerate(a) ]

for i in range(n+1,n+k+1):
    new.append((1000005,i))
q = []
for i in range(1,n+k+1):
    while q and q[-1][0]>=new[i][0]:
        q.pop()
    q.append(new[i])
    if q[0][1]<=i-2*k-1:q.pop(0)
    if i>=k+1:print(q[0][0],end=' ')

四、线段树

【基本思路】

       最基本的问题,直接套用线段树的板子就可以了。 (不过由于n是10⁶的量级卡了1个点)

【Python程序代码】

n=int(input())
def push_up(p):
    tree[p]=min(tree[p<<1],tree[p<<1|1])
def query(p,pl,pr,L,R):
    if pl>R or pr<L:
        return 1<<64
    if L<=pl and pr<=R:
        return tree[p]
    mid=(pl+pr)>>1
    return min(query(p<<1|1,mid+1,pr,L,R),query(p<<1,pl,mid,L,R))
def build(p,pl,pr):
    if pl==pr:
        tree[p]=a[pl]
    else:
        mid=(pl+pr)>>1 
        build(p<<1,pl,mid)
        build(p<<1|1,mid+1,pr)
        push_up(p)
a=[0]+list(map(int,input().split()))
tree=[0 for _ in range(n<<2+1)]
build(1,1,n)
k=int(input())
for i in range(1,n+1):
    x=max(1,i-k)
    y=min(n,i+k)
    print(query(1,1,n,x,y),end=' ')

猜你喜欢

转载自blog.csdn.net/w2563216521/article/details/134715223