涉及知识点
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 ansif cnt >= ans:returnif weight == m:ans = min(ans, cnt)if index == n or weight >= m or weight + nex[index] < m: returndfs(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 dequedq = deque()k = 2*k+1for i in range(k-1):while dq and s[i] <= s[dq[-1]]:dq.pop()dq.append(i)left = 0ans = []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 += 1return ansres = 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 = 0for i in range(21):zero = 1one = 0sum_val = 0cnt = 0for j in range(n):temp = (a[j] >> i) & 1sum_val ^= tempif sum_val == 0:zero += 1cnt += oneelse:one += 1cnt += zeroans += 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 xelse: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] = 1destory.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 -= 1merge(l, r)ans = [res]
for i in range(len(destory)-1, -1, -1):c = destory[i]res += 1broken[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 -= 1merge(c, j)ans.append(res)for i in range(len(ans)-1, -1, -1):print(ans[i])
今年的蓝桥杯总不能放弃了吧QAQ