练习赛1题解

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()

  • 34
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值