蓝桥杯模板(三)python组

单调栈

#单调栈  -> 解决「下一个更大元素」,「上一个更小元素」
#注意1:找最近的比它小的数,需要维护单调递增栈,即栈顶元素比它大的全部弹出(对于i+1来说,他们的贡献不会比i大,所以没用了)。栈顶剩下的就是最近那个。然后自己再入栈。
#注意2:找右边最近的比它小的数,需要逆序遍历。但栈依然是递增的。
#注意4:一般栈里是存下标。

#基本模板
def st(nums):
    st = []
    for num in  nums:
        while st and num >= st[-1]:  #递增  <= 递减
            st.pop()
        st.append(num)
#返回每一数下一个更大/小的数(list)
def n_st(nums):
    n = len(nums)
    res= [0]*n #存结果
    s = []
    for i in range(n-1,-1,-1): #正序遍历 逆序遍历都可  倒叙入栈==正序出栈
        while s and s[-1] <= num[i]:
             # 矮个起开,反正也被挡着了。。。
            s.pop()
        res[i] = s[-1] if s else -1
         # nums[i] 身后的更大元素
        s.append(nums[i])
    return s

单调队列

#单调队列  解决滑动窗口最值  

def wd(nums,k):
    ans = []
    q = deque() #使用双端队列
    for i in range(len(nums)):
        #1. 入 3.记录答案
        while q and nums[q[i]] <= x:
            q.pop()
        q.append(i)
         #2.出
        if i-q[0] >= k: #窗口大小>= k
            q.popleft() #队首移除窗口
        if i >= k-1:
            ans.append(nums[q[0]]) #(队列递减,队首即最大值)
    return ans


#第二种

from collection import daque

def st(nums,k):
    win = deque()
    res= []
    for i in range(len(nums)):
        if i <k-1:
            win.append(nums[i])  # 先将窗口前 k - 1 填满
        else:
             # 窗口开始向前滑动
            # 移入新元素
            win.append(nums[i])
             # 将当前窗口中的最大元素记入结果
            res.append(max(win))
            # 移出最后的元素
            win.popleft()
    return res

差分

#差分
#1.构建差分数组
for i in range(len(s)-1,0,-1):
    s[i] -= s[i-1]

#2.转换加减(区间加减->端点加减)
    s[l-1] += v
    s[r] -= v

#3.前缀相加
for i in range(1,n):
    s[i] += s[i-1]

eg:
# https://www.lanqiao.cn/problems/1276/learning/

n,q = map(int,input().split())
a = [0]+list(map(int,input().split()))

b = [0]*(n+2)
for i in range(1,n+1):
    b[i] = a[i] - a[i-1]
    
for i in range(q):
    l,r,x = map(int,input().split())
    b[l] += x
    b[r+1] -= x

for i in range(1,n+1):
    a[i] = b[i] + a[i-1]
    if a[i] <= 0:
        print(0,end =' ')
    else:
        print(a[i],end = ' ')

并查集

#并查集

def find(x):
# 如果x不是根节点,则递归地找到x的根节点,并将x的父节点更新为根节点(实现状态压缩)

    if x!= p[x]:
        p[x] = find(p[x])
    return p[x]

for i in range(n):
    a,b = map(int,input().split())
    pa,pb = find(a),find(b)  # 分别找到a和b的根节点
    if pa != pb:
        p[pa] = pb

DFS

#深搜  1.确定dfs的两个参数  2.确认终止条件 3.处理目前搜索节点出发的路径
ans = []
def dfs(层数,参数):
    if (出局判断,特况):
        更新答案
    return   

    剪枝
    for (枚举下一层的情况):
        if (vis[i]==0):
            vis[i] = 1
            dfs(层数+1,参数)#下一层
            vis[i] = 0 #回复状态,不影响回溯时的使用 
            #有时候没有显式地使用栈和回溯操作,但实际上通过递归调用实现了DFS的功能(全球变暖问题,岛屿类)。

    return

BFS

from collections import deque, defaultdict

t = ''.join(['0', '1', '2', '3', '4', '5', '6', '7', '8', 'x'])  # 目标值
d = [-1, 1, -3, 3]  # 上下移 在数组中步长为3
ls = ['0'] + list(map(str, input().split()))  # 输入态
idx = ls.index('x')  # x的初始索引
#有时候需要加入falg变量 用于判断符合
vis = defaultdict(int)  #判重数组一定要有!!!
# 记录已经访问过的状态,避免重复访问同一个状态

def bfs():
    q = deque()
    stp = 0  # 初始步数
    q.append([ls, idx, stp])

    s = ''.join(ls)
    vis[s] = 1
    res = -1  # 存储最终的结果
    while q:
        ts, tidx, stp = q.popleft()
        if ''.join(ts) == t:  # 等于目标值
            res = stp
            break
        for i in d:
            tmp = ts.copy()  # 原始状态的完整性,以便在搜索失败时回溯到上一个状态
            nidx = tidx + i
            # 出界情况
            if nidx < 1 or nidx > 9: continue
            if (tidx == 3 or tidx == 6) and i == 1: continue
            if (tidx == 4 or tidx == 7) and i == -1: continue
            # 交换位置
            tmp[tidx], tmp[nidx] = tmp[nidx], tmp[tidx]
            stmp = ''.join(tmp)
            if vis[stmp]: continue
            vis[stmp] = 1
            q.append([tmp, nidx, stp + 1])
    print(res)

bfs()
posted @   taixian  阅读(60)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示