The Python standard library commonly used in the competition

Analyze the standard library commonly used in the competition and give code templates

Table of contents

1.functools

1.1  cmp_to_key

1.2 lru_cache (memory storage, speed up return speed)

2.collections

2.1 and

2.1.1 Monotone alignment implementation

2.1.2 BFS wide search

3.sys

3.1 sys.maxsize

3.2 sys.exit()

3.3 sys.stdin.readline()

3.4  sys.setrecursionlimit()

4.heapq

4.1 heapq.heapify(x)

4.2 heapq.heappush(heap, item)

4.3 heapq.heappop(heap)

4.4 Heap-optimized Dijstra 

1. Business trip for the real questions of the Blue Bridge Cup National Competition

4.5 Kruskal's algorithm realized by heap

1. Power on the real questions of the national competition

5.itertools

5.1 combinations

5.2 permutations

5.3 Examples

1. Mathematical problems 

6.bisect

 6.1 bisect_left()

6.2 bisect_right() 、bisect()

6.3 insort_left()

6.4 insort_right()、insort()

6.5 Examples

6.6 Example 1 The longest ascending subsequence

1. Bluebridge Knights

 2. Blue Bridge Warriors

6.7 Example 2 Longest Ascending Subsequence Deformation


1.functools

1.1  cmp_to_key

Convert old-style comparison functions to key functions.

-1 No change 1 Exchange position

import functools
x=[1,3,2,4,5]
def cmp_rise(a,b):
    '''
    升序排序:
    当前面的参数a小于后面的参数b返回-1,-1代表保持不变,
    当前面的的参数a大于等于后面的参数b返回1,1代表交换顺序。
    因此保证了前面的数子小于后面的数字,是升序排序。
    '''
    if a <b:
        return -1
    else:
        return 1
def cmp_decline(a,b):
    '''
    降序排序:
    当前面的参数a小于后面的参数b返回1,1代表交换顺序,
    当前面的的参数a大于等于后面的参数b返回-1,-1代表保持不变。
    因此保证了前面的数子大于后面的数字,是降序排序。
    '''
    if a <b:
        return 1
    else:
        return -1
x_sorted_by_rise=sorted(x,key=functools.cmp_to_key(cmp_rise))
x_sorted_by_decline=sorted(x,key=functools.cmp_to_key(cmp_decline))
print(x) # 输出结果:[1, 3, 2, 4, 5]
print(x_sorted_by_rise) # 输出结果:[1, 2, 3, 4, 5]
print(x_sorted_by_decline) # 输出结果:[5, 4, 3, 2, 1]

1.2 lru_cache (memory storage, speed up return speed)

Allows us to quickly cache or uncache the return value of a function.
This decorator is used to cache the call result of the function. For a function that needs to be called multiple times, and the parameters are the same for each call, you can use this decorator to cache the call result to speed up the program.
The decorator will cache different call results in memory, so you need to pay attention to memory usage.

from functools import lru_cache
@lru_cache(maxsize=30)  # maxsize参数告诉lru_cache缓存最近多少个返回值
def fib(n):
    if n < 2:
        return n
    return fib(n-1) + fib(n-2)
print([fib(n) for n in range(10)])
fib.cache_clear()   # 清空缓存

2.collections

2.1 and

Double-ended queue, used to implement monotonic queue and BFS search


from collections import deque

q = deque(['a', 'b', 'c'], maxlen=10)
# 从右边添加一个元素
q.append('d')
print(q) # deque(['a', 'b', 'c', 'd'], maxlen=10)

# 从左边删除一个元素
print(q.popleft()) # a
print(q) # deque(['b', 'c', 'd'], maxlen=10)

# 扩展队列
q.extend(['i', 'j'])
print(q) # deque(['b', 'c', 'd', 'i', 'j'], maxlen=10)

# 查找下标
print(q.index('c')) # 1

# 移除第一个'd'
q.remove('d')
print(q) # deque(['b', 'c', 'i', 'j'], maxlen=10)

# 逆序
q.reverse()
print(q) # deque(['j', 'i', 'c', 'b'], maxlen=10)

# 最大长度
print(q.maxlen) # 10

2.1.1 Monotone alignment implementation

Blue Bridge Cup MAX most value difference

import os
import sys

# 请在此输入您的代码
from collections import deque
def findMaxdiff(n,k,a):
  q1,q2=deque(),deque()   # 建两个单调队列
  res=-sys.maxsize
  for i in range (n):  # 遍历每一个元素
    while q1 and a[q1[-1]]>=a[i]:  #q1有元素且最后一个元素都大于a[i]
      q1.pop()
    q1.append(i)
    while q1 and i-q1[0]>=k:
      q1.popleft()
    Fi=a[q1[0]]

    while q2 and a[q2[-1]]<=a[i]:  #q1有元素且最后一个元素都大于a[i]
      q2.pop()
    q2.append(i)
    while q2 and i-q2[0]>=k:
      q2.popleft()
    Gi=a[q2[0]]
    
    #计算最大差值 
    res=max(res,Gi-Fi)
  return  res


n,k=map(int,input().split())
A=list(map(int,input().split()))
print(findMaxdiff(n,k,A))

2.1.2 BFS wide search

Blue Bridge Cup real question jumping grasshopper

import collections
import sys
meet=False   #判断是否相遇

def extend(q,m1,m2):
  global meet
  s=q.popleft()
  ss=list(s)
  index=ss.index('0') #找0的索引
  for j in [1,-1,2,-2]:
    ss[(index+j+9)%9],ss[index]= ss[index],ss[(index+j+9)%9]
    a=''.join(ss)
    if a in m2:  # 找到相同的了,即相遇了
      print(m1[s]+1+m2[a])
      meet=True
      return
    if a not in m1:
      q.append(a)
      m1[a]=m1[s]+1  # 向字典中添加
    ss[(index+j+9)%9],ss[index]= ss[index],ss[(index+j+9)%9]
 # meet=False

q1=collections.deque()
q2=collections.deque()
q1.append("012345678")
q2.append("087654321")
# 字典去重,同时记录步数
mp1={'012345678':0} ; mp2={'087654321':0}
while q1 and q2 :  # 两个都不为空
  if len(q1)<=len(q2): extend(q1,mp1,mp2)
  else:  extend(q2,mp2,mp1)
  if meet==True: break

3.sys

3.1 sys.maxsize

Indicates the maximum int value carried by the operating system

3.2 sys.exit()

Interrupt program execution

3.3 sys.stdin.readline()

Read it quickly, pay attention to the carriage return character, which is not very useful and does not improve the efficiency much

import sys

a = sys.stdin.readline()
b = input()
print(len(a), len(b))

a = sys.stdin.readline().strip('\n')
b = input()
print(len(a), len(b))

输出结果
123123 123123 adsfasdfd fefeggegeag fasdfa
123123 123123 adsfasdfd fefeggegeag fasdfa
43 42
123123 123123 adsfasdfd fefeggegeag fasdfa
123123 123123 adsfasdfd fefeggegeag fasdfa
42 42

3.4  sys.setrecursionlimit()

Set the maximum recursion depth, the default is very small, sometimes dfs will report a segment error.

sys.setrecursionlimit(10**6)

4.heapq

4.1 heapq.heapify(x)

Convert list x to a heap, in-place, in linear time.

import heapq

H = [21,1,45,78,3,5]
# Use heapify to rearrange the elements
heapq.heapify(H)
print(H)


[1, 3, 5, 78, 21, 45]

4.2 heapq.heappush(heap, item)

Add the value of item to the heap, keeping the invariance of the heap.

# Add element
heapq.heappush(H,8)
print(H)


[1, 3, 5, 78, 21, 45]


[1, 3, 5, 78, 21, 45, 8]

4.3 heapq.heappop(heap)

Pops and returns the smallest element of the heap, keeping the heap invariant. If the heap is empty, IndexError is thrown. With heap[0], it is possible to access only the smallest element without popping it.

# Remove element from the heap
heapq.heappop(H)
print(H)


[1, 3, 5, 78, 21, 45, 8]


[3, 21, 5, 78, 45]

4.4 Heap-optimized Dijstra 

1. Business trip for the real questions of the Blue Bridge Cup National Competition

import os
import sys
import itertools
import heapq

# Bellman-Ford O(mn)
'''
n,m=map(int,input().split())
stay=[0]+list(map(int,input().split()))
stay[n]=0  # 终点不需要隔离
e=[]
for i in range(m):
  a,b,c=map(int,input().split())
  e.append([a,b,c])
  e.append([b,a,c])

dp=[sys.maxsize for i in range(n+1)] 
dp[1]=0  #到起点的距离为0
for i in range(1,n+1): # n个点
  for j in e:  # m条边
    v1,v2,cost=j
    #if v2==n:  # n号城市不需要隔离时间
    dp[v2]=min(dp[v2],dp[v1]+cost+stay[v2])

print(dp[n])

'''

# Dijstra  临接表写法 O(n*n)
'''
n,m=map(int,input().split())
stay=[0]+list(map(int,input().split()))
stay[n]=0  # 终点不需要隔离
edge=[[]for i in range(n+1)]
for i in range(m):
  a,b,c=map(int,input().split())
  edge[a].append([b,c+stay[b]])
  edge[b].append([a,c+stay[a]])

hp=[]
vis=[0 for i in range(n+1)]
dp=[sys.maxsize for i in range(n+1)]
dp[1]=0  # 自身到自身距离为0
heapq.heappush(hp,(0,1)) 
while hp:
  u=heapq.heappop(hp)[1]
  if vis[u]:
    continue
  vis[u]=1
  for i in range(len(edge[u])): # 遍历u的边
    v,w=edge[u][i][0],edge[u][i][1]
    if vis[v]:
      continue
    if dp[v]>dp[u]+w:
      dp[v]=dp[u]+w
      heapq.heappush(hp,(dp[v],v))    

print(dp[n])
'''


# Dijstra临接矩阵写法  O(n*n)
'''
n,m=map(int,input().split())
stay=[0]+list(map(int,input().split()))
stay[n]=0  # 终点不需要隔离
edge=[[sys.maxsize for i in range(n+1)]for i in range(n+1)]
for i in range(m):
  a,b,c=map(int,input().split())
  edge[a][b]=c+stay[b]
  edge[b][a]=c+stay[a]

vis=[0 for i in range(n+1)]
dp=[sys.maxsize for i in range(n+1)]
dp[1]=0  # 自身到自身距离为0

for i in range(n-1):   #只需要处理n-1个点
  t=-1
  for j in range(1,n+1):   # 找到没处理过得并且距离最小的
    if vis[j]==0 and(t==-1 or dp[j]<dp[t] ):
      t=j
  for j in range(1,n+1):
    dp[j]=min(dp[j],dp[t]+edge[t][j])
  vis[t]=1

print(dp[n])
'''

# SPFA
n,m=map(int,input().split())
stay=[0]+list(map(int,input().split()))
stay[n]=0  # 终点不需要隔离
edge=[[]for i in range(n+1)]   #临接表存边
for i in range(m):
  a,b,c=map(int,input().split())
  edge[a].append([b,c+stay[b]])
  edge[b].append([a,c+stay[a]])
  
dp=[sys.maxsize for i in range(n+1)]
dp[1]=0  # 自身到自身距离为0


def spfa():
  hp=[]
  heapq.heappush(hp,1)   #用堆实现相当于优先队列,加快一点效率罢了
  in_hp=[0 for i in range(n+1)]  # 标记数组换为了判断是否在队列中 
  in_hp[1]=1  # 1在队列
  while hp:
    u=heapq.heappop(hp)
    in_hp[u]=0  # 标记为不在队列
    if dp[u]==sys.maxsize:   # 没有处理过的点,直接跳过,只处理邻居点
      continue
    for i in range(len(edge[u])): # 遍历u的边
      v,w=edge[u][i][0],edge[u][i][1]
      if dp[v]>dp[u]+w:
        dp[v]=dp[u]+w
        if in_hp[v]==0: # 他的邻居不再队列,就把他入队,方便下下次更新邻居的邻居结点
          heapq.heappush(hp,v)    
          in_hp[v]=1
spfa()
print(dp[n])

4.5 Kruskal's algorithm realized by heap

1. Power on the real questions of the national competition

import os
import sys
import math
import heapq # heapq 比 优先队列要快很多

input = sys.stdin.readline

n = int(input().strip())

root = [i for i in range(n+1)]

arr = [list(map(int, input().strip().split())) for i in range(n)] # n个点坐标 高度

# 计算距离
def dist(x1,y1,h1, x2,y2,h2):
  
  return math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)) + (h1-h2)*(h1-h2)

q = []
# 建立 n个点的的连通图
for i in range(n):
  for j in range(i+1,n):
    heapq.heappush(q, [dist(arr[i][0],arr[i][1],arr[i][2], arr[j][0],arr[j][1],arr[j][2]), i, j]) # 从 i到j牵线,并按距离排序

# 判断是否会形成环
def find(u):

  if u != root[u]:
    root[u] = find(root[u])

  return root[u]

# Kruskal 算法实现步骤

def Kruskal():

  ans = 0.00
  cnt = 0

  while q and cnt < n-1: # 图只需找n-1条边
    c,a,b = heapq.heappop(q)

    a_root = find(a)
    b_root = find(b)

    if a_root != b_root:
      root[a_root] = b_root
      ans += c
      cnt += 1

  print('%.2lf' % ans)

Kruskal()


"""
import os
import sys

# 请在此输入您的代码
import math
n=int(input())
def money(a,b):
    ke=math.sqrt(pow(a[0]-b[0],2)+pow(a[1]-b[1],2))+pow(a[2]-b[2],2)
    return ke
def prim():
    global res
    dist[0]=0
    book[0]=1
    for i in range(1,n):
        dist[i]=min(dist[i],G[0][i])
    for i in range(1,n):
        cnt=float("inf")
        t=-1
        for j in range(1,n):
            if book[j]==0 and dist[j]<cnt:
                cnt=dist[j]
                t=j
        if t==-1 :
            res=float("inf")
            return
        book[t]=1
        res+=dist[t]
        for j in range(1,n):
            dist[j]=min(dist[j],G[t][j])
             
ls=[]
book=[0]*n
dist=[float("inf")]*n
res=0
for i in range(n):
    ls.append(list(map(int,input().split())))
G=[[float("inf")]*n for _ in range(n)]
for i in range(n):
    G[i][i]=float("inf")
for i in range(n):
    for j in range(i+1,n):
        G[i][j]=money(ls[i],ls[j])
        G[j][i]=money(ls[i],ls[j])
prim()
print("{:.2f}".format(res))

"""

5.itertools

Mainly use combinations and combinations.

5.1 combinations

itertools.combinations(iterable, r): Generate all combinations of length r of an iterable object.

5.2 permutations

itertools.permutations(iterable, r=None): Generate all permutations of length r of the iterable object. The default r is the length of the iterable object.

5.3 Examples

1. Mathematical problems 

import os
import sys
import itertools
# 请在此输入您的代码
L=[str(i) for i in range(1,10)]

ans=0
for i in itertools.permutations(L):
    s=''.join(i)
    if int(s[:3])+int(s[3:6])==int(s[6:]):
        ans+=1

print(ans)

6.bisect

Built-in binary search function for insertion and search of ordered sequences

 6.1 bisect_left()

bisect.bisect_left(a, x, lo=0, hi=len(a))

If x ∈ a, return the leftmost index of x; otherwise return the index of the right neighbor of x, so that x can be located on its left after insertion. 

6.2 bisect_right() 、bisect()

bisect.bisect(a, x, lo = 0, hi =len(a))
bisect.bisect_right(a, x, [lo=0, hi=len(a)])

If x ∈ a, return the leftmost index of x; otherwise return the index of the right neighbor of x, so that x can be located on its left after insertion. 

6.3 insort_left()

bisect.insort_left(a, x, lo=0, hi=len(a))

bisect.bisect_left() Find the insertion point (left side) of element x in sequence 
a. bisect.insort_left() inserts element x into sequence a based on finding the insertion point, thereby changing sequence a while maintaining the order of elements.

6.4 insort_right()、insort()

bisect.insort(a, x, lo=0, hi=len(a))
bisect.insort_right(a, x, lo=0, hi=len(a))

6.5 Examples

import bisect
 
nums = [0,1,2,3,4,4,6]
idx = bisect.bisect_left(nums,-1) # 0
idx = bisect.bisect_left(nums,8) # 7
idx = bisect.bisect_left(nums,3) # 3
idx = bisect.bisect_left(nums,3.5) # 4
idx = bisect.bisect_left(nums,4) # 4
idx = bisect.bisect_left(nums,3,1,4) # 3

a = [1,4,6,8,12,15,20]
position = bisect.bisect(a,13)
print(position) # 5
 
# 用可变序列内置的 insert 方法插入
a.insert(position, 13)
print(a)  # 5 [1, 4, 6, 8, 12, 13, 15, 20]

 The number you are looking for is not in the list

import bisect
list1 = [1,3,5,7,9,11,11,11,11,11,13]
a = bisect.bisect(list1,6)
b = bisect.bisect_left(list1,6)
c = bisect.bisect_right(list1,6)
print(a,b,c)
# 输出为 3,3,3

 The searched number is only one in the list

import bisect
list1 = [1,3,5,7,9,11,11,11,11,11,13]
a = bisect.bisect(list1,9)
b = bisect.bisect_left(list1,9)
c = bisect.bisect_right(list1,9)
print(a,b,c)
# 输出 5,4,5

The searched number is more than one in the list

import bisect
list1 = [1,3,5,7,9,11,11,11,11,11,13]
a = bisect.bisect(list1,11)
b = bisect.bisect_left(list1,11)
c = bisect.bisect_right(list1,11)
print(a,b,c)
# 输出是 10,5,10

6.6 Example 1 The longest ascending subsequence

1. Bluebridge Knights

import os
import sys
'''
# 最长上升子序列

n = int(input())
a = list(map(int,input().split()))
f = [1]*n
for i in range(1,n):
       for j in range(i):
              if a[i] > a[j]:
                     f[i] = max(f[i],f[j]+1)
print(max(f))
'''
# 超时
'''
import bisect
n = int(input())
a = list(map(int,input().split()))
b = [a[0]]
for i in range(1,n):
       t = bisect.bisect_left(b,a[i])
       # 若b中不存在a[i],t是适合插入的位置
       # 若b中存在a[i],t是a[i]第一个出现的位置
       if t == len(b): # 插入的位置是否是末尾
              b.append(a[i])
       else:
              b[t] = a[i]
print(len(b))

'''
import bisect
#蓝桥骑士 dp lis(Longest Increasing Subsequence)
n = int(input())
alist = list(map(int,input().split()))
dp = []
for i in alist:
    if not dp or i > dp[-1]:
        dp.append(i)
    else:
        index = bisect.bisect_left(dp,i)
        dp[index]=i
print(len(dp))

 2. Blue Bridge Warriors

import sys  #设置递归深度
import collections  #队列
import itertools  # 排列组合
import heapq  #小顶堆
import math
sys.setrecursionlimit(300000)

n=int(input())
save=[0]+list(map(int,input().split()))
dp=[1]*(n+1)  # 注意初始化从1开始
for i in range(2,n+1):
   for j in range(1,i):
      if save[i]>save[j]:
         dp[i]=max(dp[i],dp[j]+1)
print(max(dp))   #最长公共子序列,dp[n]不一定是最大的

# 1 4 5 2 1
# 1 2 3 2 1

6.7 Example 2 Longest Ascending Subsequence Deformation

import bisect  # 内置二分查找
zifu = input()
A = [chr(65 + i) for i in range(26)]
s = ""
name = []
i = 0
zifu = zifu + "A"  # 以后一个大写字符进行提取分隔
while i < len(zifu) - 1:  # 提取数据格式为     name=[Wo,Ai,Lan,Qiao,Bei]
    s += zifu[i]
    if zifu[i + 1] in A:
        name.append(s)
        s = ""
    i += 1
d = [name[0]]
p=[1]  #存储下标
for i in name[1:]:  # 遍历每一个字符
    if i > d[-1]:  # 大于,可以直接在后面接着
        d.append(i)  # 后面添加
        p.append(len(d))  # 记录索引
    else:  # 查找第一个
        k = bisect.bisect(d, i)  # 使用bisect查找d中第一个大于等于i的元素,让其称为递增序列,有多个就是最右边的那个
        if k > 0 and d[k - 1] == i:  # 如果右索引的前一个数等于这个i的话,就将它替换掉,相等的不算递增????
            k -= 1
        d[k] = i
        p.append(k+1)  # 记录替换的索引

p0=p[::-1]  #逆序遍历输出
s=len(d) # 最长有多少个递增子序列
ans=""
for i in range(len(p0)):  #逆序遍历
    if s==0:
        break
    if p0[i]==s:
        ans=name[len(p)-i-1]+ans  #加上name
        s=s-1
print(ans)

Guess you like

Origin blog.csdn.net/weixin_52261094/article/details/131019840