A.
题目链接:A-先发个奖学金_练习赛1 (nowcoder.com)
题干:
某小学最近得到了一笔赞助,打算拿出其中一部分为学习成绩优秀的前5名学生发奖学金。期末,每个学生都有3门课的成绩:语文、数学、英语。先按总分从高到低排序,如果两个同学总分相同,再按语文成绩从高到低排序,如果两个同学总分和语文成绩都相同,那么规定学号小的同学 排在前面,这样,每个学生的排序是唯一确定的。
任务:先根据输入的3门课的成绩计算总分,然后按上述规则排序,最后按排名顺序输出前五名名学生的学号和总分。注意,在前5名同学中,每个人的奖学金都不相同,因此,你必须严格按上述规则排序。例如,在某个正确答案中,如果前两行的输出数据(每行输出两个数:学号、总分) 是:
7 279
5 279
这两行数据的含义是:总分最高的两个同学的学号依次是7号、5号。这两名同学的总分都是 279 (总分等于输入的语文、数学、英语三科成绩之和) ,但学号为7的学生语文成绩更高一些。如果你的前两名的输出数据是:
5 279
7 279
则按输出错误处理,不能得分。
题解:
本题是多参数排序问题,只需要按照题干的优先级顺序排序即可
只有一个参数时:
使用sort()排序
x.sort()会默认从小到大排序
有多个参数时:
x.sort(key=lambda x:(x[0],-x[1]))表示先按照第一个参数从小到大排序,之后再按照第二个参数从大到小排序
本题代码:
n=int(input())
x=[]
for i in range(n):
a=list(map(int,input().split()))
a.append(a[0]+a[1]+a[2])
a.append(i+1)
x.append(a)
x.sort(key=lambda x:(-x[3],-x[0],x[4]))
for i in range(5):
print(x[i][4],end=" ")
print(x[i][3])
B.
题目链接:B-再认一个亲戚_练习赛1 (nowcoder.com)
题干:
DongDong每年过春节都要回到老家探亲,然而DongDong记性并不好,没法想起谁是谁的亲戚(定义:若A和B是亲戚,B和C是亲戚,那么A和C也是亲戚),她只好求助于会编程的你了。
题解:
本题是很裸的并查集模板题,但是有一个地方需要注意,需要先将字符串通过字典映射为数字,之后就变成的熟悉的模板题
代码:
def find(x):
if p[x]!=x:
p[x]=find(p[x])
return p[x]
n,m=map(int,input().split())
s=list(input().split())
mp=dict()
p=[0]*(n+10)
for i in range(len(s)):
mp[s[i]]=i
for _ in range(n+1):
p[_]=_
for _ in range(m):
op,x,y=input().split()
op=int(op)
if op==1:
p[find(mp[x])]=find(mp[y])
else :
if find(mp[x])==find(mp[y]):
print(1)
else :
print(0)
C.
题目链接:C-之后吐个小泡泡_练习赛1 (nowcoder.com)
题干:
小鱼儿吐泡泡,嘟嘟嘟冒出来。小鱼儿会吐出两种泡泡:大泡泡"O",小泡泡"o"。 两个相邻的小泡泡会融成一个大泡泡,两个相邻的大泡泡会爆掉。 (是的你没看错,小气泡和大气泡不会产生任何变化的,原因我也不知道。) 例如:ooOOoooO经过一段时间以后会变成oO。
题解:
可以看出本题需要用栈模拟,我们先将泡泡入栈,然后从栈底依次判断栈底的两个字符的变化即可(两个相邻的小泡泡会融成一个大泡泡,两个相邻的大泡泡会爆掉。)
代码:
while True:
try:
s=list(input())
x=[]
#print(s)
for _ in range(len(s)):
x.append(s[_])
while (len(x)>1 and x[-1]=='o' and x[-2]=='o'):
x.pop()
x.pop()
x.append('O')
while(len(x)>1 and x[-1]=='O' and x[-2]=='O'):
x.pop()
x.pop()
for i in range(len(x)):
print(x[i],end="")
print()
except:
break
D.
题目链接:D-打个小扑克_练习赛1 (nowcoder.com)
题干:
你有n种牌,第i种牌的数目为ci。另外有一种特殊的牌:joker,它的数目是m。你可以用每种牌各一张来组成一套牌,也可以用一张joker和除了某一种牌以外的其他牌各一张组成1套牌。比如,当n=3时,一共有4种合法的套牌:{1,2,3}, {J,2,3}, {1,J,3}, {1,2,J}。 给出n, m和ci,你的任务是组成尽量多的套牌。每张牌最多只能用在一副套牌里(可以有牌不使用)。
题解:
易错点:鸽巢原理
思路是二分答案
check函数的思路:
定义变量res是需要的joker牌的个数
假设x是答案,遍历每种牌,如果这种牌的个数小于x,那么res就加上x和这种牌的个数之差, 最后遍历完所有种类的牌之后,如果res的个数小于等于现有的joker牌的个数,并且需要的joker牌的数量小于等于x(因为每套牌里面只能有一个joker,所以如果需要的joker的数量大于了套牌的数量,那么根据鸽巢原理,一定会有至少一套牌里面有两个joker,就会与题意相违背),check函数就返回true,否则返回false
代码:
def check(x):
res=0
for i in range(n):
if a[i]<x:
res+=x-a[i]
if res<=m and res<=x:
return True
return False
n,m=map(int,input().split())
a=list(map(int,input().split()))
l,r=min(a),10**10
while(l<r):
mid=(l+r+1)//2
if check(mid):
l=mid
else :
r=mid-1
print(l)
G.
题目链接:G-求第k小的数_练习赛1 (nowcoder.com)
题干:
有一个长度为n的数组,值为 a[i], 牛牛想找到数组中第 k 小的数。比如 1 2 2 3 4 6 中,第 3 小的数就是2.牛牛觉得这个游戏太简单了,想加一点难度,现在牛牛有 m 个操作,每个操作有两种类型。
1 x 1 代表操作一,给数组中加一个元素 x 。(0 ≤ x ≤ 1e9)
2 2 代表操作二,查询第 k 小的数。如果没有 k 个数就输出−1
题解:
本题数组一直是动态变化的,如果每次都用sort排序的话,复杂度过高,因此我们用优先队列,推入和删除复杂度都是o(logn)。
因为让求的是第k小的数,因此我们可以用大根堆(队列从大到小排序),保持队头一直是最大值,只需要控制队列的长度一直为k,这时队头就是第k小的数
代码:
from heapq import heappush,heappop,heapify
n,m,k=map(int,input().split())
q=list(map(int,input().split()))
for i in range(len(q)):
q[i]=-q[i]
heapify(q)
while len(q)>k:
heappop(q)
for _ in range(m):
s=input()
if len(s)==1:
if len(q)<k:
print(-1)
else :
s=int(s)
while(len(q)>k):
heappop(q)
x=-heappop(q)
print(x)
heappush(q,-x)
else :
s=list(s.split())
x=int(s[1])
heappush(q,-x)
while(len(q)>k):
heappop(q)
H.
题目链接:H-再来个K序列_练习赛1 (nowcoder.com)
题干:
给一个数组 a,长度为 n,若某个子序列中的和为 K 的倍数,那么这个序列被称为“K 序列”。现在要你 对数组 a 求出最长的子序列的长度,满足这个序列是 K 序列。
题解:
由于1 ≤ nK ≤ 107,因此我们直接用前缀和两层for循环暴力求解即可
首先枚举长度,长度len从n到1枚举,第二层循环遍历整个数组,如果长度为len的元素的和是k的倍数的话,直接返回len(此时len就是最终答案)
代码:
def solve():
for len in range(n,0,-1):
for i in range(1,n-len+2):
if (a[i+len-1]-a[i-1])%k==0:
print(len)
return True
n,k=map(int,input().split())
a=[0]*(n+10)
a[1:n+1]=map(int,input().split())
for i in range(1,n+1):
a[i]+=a[i-1]
solve()