蓝桥杯复盘记录004(2023)

涉及知识点

1.深搜

2.单调队列+滑动窗口

3.位运算

4.并查集

题目

1.lanqiao3505

思路:

dfs(index, weight, cnt) index表示瓜的索引, weight等于买瓜的重量, cnt表示买了多少瓜。

递归终止条件:1.如果瓜买完了,归

                         2.如果正好为目标重量,记录最小的切瓜次数

                          3. 如果最后一个瓜已经走过或重量已经超了, 或者从索引index后所有瓜买了也到不了目标重量直接return

为了方便计算,都乘2,并且排序

买整个第index瓜, dfs(index+1, weight +a[index], cnt)

买第index的一半 ,dfs(index+1, weight+a[index] // 2, cnt+1),切瓜次数+1

不买第index个瓜, dfs(index+1, weight, cnt)

很有意思的地方,条件判断的时候要首先判断瓜是不是已经最后一个瓜也就是最小的那个瓜已经判断过,然后判断重量是不是已经超过目标重量, 最后判断是不是当前重量加上所有后面的小瓜不到目标重量,说明往后dfs没用,直接return.

from itertools import accumulate
# 三种可能,买,买一半,不买
def dfs(index, weight, cnt):
    global ans
    if cnt >= ans:
        return
    if weight == m:
        ans = min(ans, cnt)
    if index == n or weight >= m or weight + nex[index] < m: 
        return

    dfs(index + 1, weight + a[index], cnt)
    dfs(index + 1, weight + a[index] // 2, cnt + 1)
    dfs(index + 1, weight, cnt)

n, m = map(int, input().split())
a = list(map(int, input().split()))
a.sort()
m <<= 1
a = [x << 1 for x in a]
nex = list(accumulate(a))
a = a[::-1]
nex = nex[::-1]

ans = n + 1
dfs(0, 0, 0)
print(-1 if ans == n + 1 else ans)

2.lanqiao2415

思路:

在字符串前面和后面拼接len为k的列表,列表中填充为inf。建立单调队列dq,先在0-k-1之间更新单调队列, 维持单调队列是队首最小,到队尾逐渐增大。while dq and s[i] <= s[dq[-1]] 。

然后从left开始记录res

如果队首索引在窗口之外,即if dq[0] == left: dq.pop() 并且left += 1 在这个过程中依然需要维持单调队列。

import os
import sys
from typing import List 
n = int(input())
s = list(map(int, input().split()))
k = int(input())

s = [float('inf')] * (k) + s + [float('inf')] * (k)
def slide_up(s: List[int], k: int) -> List[int]:
    from collections import deque
    dq = deque()
    k = 2*k+1
    for i in range(k-1):
        while dq and s[i] <= s[dq[-1]]:
            dq.pop()
        dq.append(i)
    
    left = 0
    ans = []
    for right in range(k-1, len(s)):
        while dq and s[right] <= s[dq[-1]]:
            dq.pop()
        dq.append(right)
        ans.append(s[dq[0]])
        if dq[0] == left:
            dq.popleft()
        left += 1
    return ans

res = slide_up(s, k)
for e in res:
  print(e, end=" ")

3.lanqiao3507

思路:

首先根据题目,知道它不会超过21位, 遍历顺序就是从第一位到第二十位,第一个数字到最后一个数字,如果sum_val 为0说明当前和和之前和为1的可以异或和为1,反之亦然。然后当sum_val 为0的时候, cnt += one 当sum_val为1时,cnt += zero这里就是初始化zero为1的原因。

对于样例来说:1 2 3 4 5

其实就是:

001

010

011

100

101

对第一列异或和为1的情况:

10

01

10

01

010

111

100

1101

10101

总共九种

39 = 1*9 + 2*5+4*5

n = int(input())
a = list(map(int, input().split()))
ans = 0

for i in range(21):
    zero = 1
    one = 0
    sum_val = 0
    cnt = 0
    for j in range(n):
        temp = (a[j] >> i) & 1
        sum_val ^= temp
        if sum_val == 0:
            zero += 1
            cnt += one
        else:
            one += 1
            cnt += zero
    ans += cnt *(1 << i)
print(ans)

4.lanqiao828

思路:

这道题一看就是并查集的思路,前一部分就是模板。graph建图无向图。建立broken列表,1表示已经破坏,0表示未被破坏,其中的一个思路是,先全部破坏,然后重建。如果l, r没被破坏并且l, r的父亲们不是同一个则res -= 1,l,r连接起来。然后就是重建的过程,for i in range(k),倒叙,res += 1,假设不联通则res += 1, broken[c] = 0说明建好了,对和c相连的j遍历,如果j不是被破坏的,并且两个没有相同的父亲,则res -= 1,两个连起来。

n, m = map(int, input().split())
maxm = 200000
fa = list(range(n+1))

def find(x):
    if fa[x] == x:
        return x
    else:
        fa[x] = find(fa[x])
        return fa[x] 
def merge(x, y):
    fa[find(x)] = find(y)

graph = [[] for _ in range(maxm)]
come = [0]*maxm
to = [0]*maxm
for i in range(m):
    a, b = map(int, input().split())
    graph[a].append(b)
    graph[b].append(a)
    come[i] = a 
    to[i] = b 

destory = []
broken =  [0]*(n+1)
k = int(input())
for i in range(k):
    a = int(input())
    broken[a] = 1
    destory.append(a)

res = n-k
for i in range(m):
    l = come[i]
    r = to[i]
    fa_l = find(l)
    fa_r = find(r)
    if not broken[l] and not broken[r] and fa_l != fa_r:
        res -= 1
        merge(l, r)

ans = [res]
for i in range(len(destory)-1, -1, -1):
    c = destory[i]
    res += 1
    broken[c] = 0 
    for j in graph[c]:
        fa_c = find(c)
        fa_j = find(j)
        if not broken[j] and fa_c != fa_j:
            res -= 1
            merge(c, j)
    ans.append(res)

for i in range(len(ans)-1, -1, -1):
    print(ans[i])

今年的蓝桥杯总不能放弃了吧QAQ

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值