2026.5.20 月考记录
Huffman编码树
贪心地可知,Huffman编码的方式可使题目所求式子最小。
import heapq
n=int(input())
a=list(map(int,input().split()))
q=[]
for i in a:
heapq.heappush(q,i)
ans=0
while(len(q)>1):
x=heapq.heappop(q)
y=heapq.heappop(q)
ans+=x+y
heapq.heappush(q,x+y)
print(ans)
兔子与樱花
使用Floyd求出全图最短路。记录路径的方法是对每一组起点和终点,记录起点下一步的点,并在松弛操作时更新。
from collections import defaultdict
from math import inf
p=int(input())
d=defaultdict(int)
name=[]
for i in range(p):
s=input()
d[s]=i
name.append(s)
a=[[inf for _ in range(p)]for _ in range(p)]
q=int(input())
next=[[0 for _ in range(p)]for _ in range(p)]
for i in range(q):
x,y,z=input().split()
idxx=d[x]
idxy=d[y]
a[idxx][idxy]=min(a[idxx][idxy], int(z))
a[idxy][idxx]=min(a[idxy][idxx], int(z))
for i in range(p):
for j in range(p):
if(i!=j and a[i][j]!=inf):
next[i][j]=j
else:
next[i][j]=-1
for k in range(p):
for i in range(p):
for j in range(p):
if(a[i][k]+a[k][j]<a[i][j]):
a[i][j]=a[i][k]+a[k][j]
next[i][j]=next[i][k]
r=int(input())
for i in range(r):
x,y=input().split()
idxx=d[x]
idxy=d[y]
cur=idxx
nxt=next[idxx][idxy]
while(cur!=idxy):
print(f"{name[cur]}->({a[cur][nxt]})->",end="")
cur=nxt
nxt=next[cur][idxy]
print(name[idxy])
两座孤岛最短距离
dfs求连通块找到一个孤岛,并从这个岛上每个点对另一个岛bfs找最短路。
from collections import deque
n=int(input())
a=[]
vis=[[0 for _ in range(n)]for _ in range(n)]
dx=[-1,0,1,0]
dy=[0,1,0,-1]
q=deque()
def dfs(x,y):
for i in range(4):
xx=x+dx[i]
yy=y+dy[i]
if(xx>=0 and xx<n and yy>=0 and yy<n):
if(vis[xx][yy]==0 and a[xx][yy]=="1"):
vis[xx][yy]=1
q.append((xx,yy,0))
dfs(xx,yy)
for i in range(n):
a.append(list(input()))
flag=0
for i in range(n):
if(flag==1):
break
for j in range(n):
if(a[i][j]=="1"):
vis[i][j]=1
q.append((i,j,0))
dfs(i,j)
flag=1
break
for i in range(n):
for j in range(n):
if(vis[i][j]==1):
a[i][j]='0'
while(q):
x,y,dis=q.popleft()
if(a[x][y]=="1"):
print(dis-1)
break
for i in range(4):
xx=x+dx[i]
yy=y+dy[i]
if(xx>=0 and xx<n and yy>=0 and yy<n):
if(vis[xx][yy]==0):
vis[xx][yy]=1
q.append((xx,yy,dis+1))
宝藏二叉树
树形dp.两个dp数组分别记录以i为根,选/不选i时整棵子树的最大值。从下往上更新。
n=int(input())
a=[0]+list(map(int,input().split()))
dp1=[0 for _ in range(n+1)]#以i为根,选i
dp2=[0 for _ in range(n+1)]#以i为根,不选i
for i in range(n,0,-1):
left=i<<1
right=(i<<1)|1
dp1[i]=a[i]
if(left<=n):
dp1[i]+=dp2[left]
dp2[i]+=max(dp1[left],dp2[left])
if(right<=n):
dp1[i]+=dp2[right]
dp2[i]+=max(dp1[right],dp2[right])
print(max(dp1[1],dp2[1]))
Catenyms
对每个单词建立从第一个字母指向最后一个字母的有向边,题目转化为求欧拉路径。通过入度与出度判断是否存在合法的路径以及起点,然后使用Hierholzer算法,dfs搜索,每次经过一条边即删除,并在当前点无出边时将该点倒序加入答案路径。
from collections import defaultdict
import sys
sys.setrecursionlimit(10**7)
t=int(input())
for _ in range(t):
n=int(input())
words=[]
for i in range(n):
tmp=input()
words.append(tmp)
words.sort()
a=defaultdict(list)
in_deg=defaultdict(int)
out_deg=defaultdict(int)
for i in range(n):
start=words[i][0]
end=words[i][-1]
a[start].append((end,words[i],i))
out_deg[start]+=1
in_deg[end]+=1
flag=0
m=len(in_deg)
start=""
end=""
for i in a.keys():
if(out_deg[i]-in_deg[i]==1):
if(start==""):
start=i
else:
flag=1
break
elif(in_deg[i]-out_deg[i]==1):
if(end==""):
end=i
else:
flag=1
break
elif(in_deg[i]!=out_deg[i]):
flag=1
break
if(flag==1):
print("***")
continue
if(start==""):
start=min(a.keys())
ans=[]
vis=[0]*n
def dfs(x):
for i in range(len(a[x])):
end,word,idx=a[x][i]
if(vis[idx]==0):
vis[idx]=1
dfs(end)
ans.append(word)
dfs(start)
if(len(ans)!=n):
print("***")
else:
ans.reverse()
print(".".join(ans))
力场叠加模拟
使用lazy tag的线段树。
class SegmentTree:
def __init__(self,n,nums):
self.n=n
self.nums=nums
self.tree=[0]*(n*4)
self.lazy=[0]*(n*4)
self.build(1,1,n)
def pushup(self,node):
self.tree[node]=max(self.tree[node*2],self.tree[node*2+1])
def pushdown(self,node,l,r):
if(self.lazy[node]!=0):
mid=(l+r)>>1
self.tree[node*2]+=self.lazy[node]
self.tree[node*2+1]+=self.lazy[node]
self.lazy[node*2]+=self.lazy[node]
self.lazy[node*2+1]+=self.lazy[node]
self.lazy[node]=0
def build(self,node,l,r):
if(l==r):
self.tree[node]=self.nums[l]
return
mid=(l+r)>>1
self.build(node*2,l,mid)
self.build(node*2+1,mid+1,r)
self.pushup(node)
def update_range(self,node,start,end,l,r,val):
if(l<=start and end<=r):
self.tree[node]+=val
self.lazy[node]+=val
return
if(end<l or start>r):
return
self.pushdown(node,start,end)
mid=(start+end)>>1
self.update_range(node*2,start,mid,l,r,val)
self.update_range(node*2+1,mid+1,end,l,r,val)
self.pushup(node)
def query(self,node,start,end,l,r):
if(l<=start and end<=r):
return self.tree[node]
if(end<l or start>r):
return 0
self.pushdown(node,start,end)
mid=(start+end)>>1
return max(self.query(node*2,start,mid,l,r),self.query(node*2+1,mid+1,end,l,r))
n,q=map(int,input().split())
tree=SegmentTree(n,[0]*(n+1))
for _ in range(q):
s=input().split()
op=s[0]
if(op=='Add'):
l,r,v=map(int,s[1:])
tree.update_range(1,1,n,l,r,v)
elif(op=="Query"):
l,r=map(int,s[1:])
print(tree.query(1,1,n,l,r))

浙公网安备 33010602011771号