牛客小白赛复盘] 牛客小白月赛74

news2024/11/26 18:32:35

[牛客小白赛复盘] 牛客小白月赛74

    • 总结
    • A 简单的整除
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • B 整数划分
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • C 传送阵
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • D 修改后的和
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • E 幼稚园的树2
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • F 最便宜的构建
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • G 跳石头,搭梯子
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • 六、参考链接

总结

  • 做了5题就下班跑路了哈哈,路上看了FG题面,G不会证明。
  • A 模拟。
  • B 模拟。
  • C 贪心+哈希表。
  • D 贪心排序
  • E 分类讨论,数学
  • F 二分答案+并查集
  • G 单调栈+贪心+树状数组RURQ
  • 在这里插入图片描述

A 简单的整除

链接: [简单的整除](https://ac.nowcoder.com/acm/contest/59284/A

1. 题目描述

在这里插入图片描述

2. 思路分析

  • 模拟。

3. 代码实现

# Problem: 简单的整除
# Contest: NowCoder
# URL: https://ac.nowcoder.com/acm/contest/59284/A
# Memory Limit: 524288 MB
# Time Limit: 2000 ms

import sys
import random
from types import GeneratorType
import bisect
import io, os
from bisect import *
from collections import *
from contextlib import redirect_stdout
from itertools import *
from array import *
from functools import lru_cache, reduce
from heapq import *
from math import sqrt, gcd, inf
if sys.version >= '3.8':  # ACW没有comb
    from math import comb

RI = lambda: map(int, sys.stdin.buffer.readline().split())
RS = lambda: map(bytes.decode, sys.stdin.buffer.readline().strip().split())
RILST = lambda: list(RI())
DEBUG = lambda *x: sys.stderr.write(f'{str(x)}\n')
# print = lambda d: sys.stdout.write(str(d) + "\n")  # 打开可以快写,但是无法使用print(*ans,sep=' ')这种语法,需要print(' '.join(map(str, p))),确实会快。

DIRS = [(0, 1), (1, 0), (0, -1), (-1, 0)]  # 右下左上
DIRS8 = [(0, 1), (1, 1), (1, 0), (1, -1), (0, -1), (-1, -1), (-1, 0),
         (-1, 1)]  # →↘↓↙←↖↑↗
RANDOM = random.randrange(2**62)
MOD = 10**9 + 7
PROBLEM = """
"""


def lower_bound(lo: int, hi: int, key):
    """由于3.10才能用key参数,因此自己实现一个。
    :param lo: 二分的左边界(闭区间)
    :param hi: 二分的右边界(闭区间)
    :param key: key(mid)判断当前枚举的mid是否应该划分到右半部分。
    :return: 右半部分第一个位置。若不存在True则返回hi+1。
    虽然实现是开区间写法,但为了思考简单,接口以[左闭,右闭]方式放出。
    """
    lo -= 1  # 开区间(lo,hi)
    hi += 1
    while lo + 1 < hi:  # 区间不为空
        mid = (lo + hi) >> 1  # py不担心溢出,实测py自己不会优化除2,手动写右移
        if key(mid):  # is_right则右边界向里移动,目标区间剩余(lo,mid)
            hi = mid
        else:  # is_left则左边界向里移动,剩余(mid,hi)
            lo = mid
    return hi


def bootstrap(f, stack=[]):
    def wrappedfunc(*args, **kwargs):
        if stack:
            return f(*args, **kwargs)
        else:
            to = f(*args, **kwargs)
            while True:
                if type(to) is GeneratorType:
                    stack.append(to)
                    to = next(to)
                else:
                    stack.pop()
                    if not stack:
                        break
                    to = stack[-1].send(to)
            return to

    return wrappedfunc


def solve():
    x, = RI()
    print("YES" if x % 2 == 0 or x % 3 == 0 or x % 5 == 0 or x % 7 == 0 else 'NO') 


if __name__ == '__main__':
    t = 0
    if t:
        t, = RI()
        for _ in range(t):
            solve()
    else:
        solve()

B 整数划分

链接: 整数划分

1. 题目描述

在这里插入图片描述

2. 思路分析

  • 由于要最小字典序,那么前边就是1 2 3 4…连续的。
  • 那么为了不使用重复数,最后一个数一定要>倒数第二个数。拆分时要注意。

3. 代码实现

def solve():
    n, = RI()
    ans = []
    i = 1
    while True:
        if n-i > i:
            ans.append(i)
            n -= i
            i += 1
        else:
            ans.append(n)
            break
    print(*ans)

C 传送阵

链接: 传送阵

1. 题目描述

在这里插入图片描述

2. 思路分析

  • 题目看似唬人,仔细想想就会发现,每次花费代价可以经过一类数字所有。而且一定可以移动到边界上,去下一个数。
  • 那么所有数字去重看看有多少种即可。

3. 代码实现

def solve():
    n,m = RI()
    s = set()
    for _ in range(n):
        r = RILST()
        s|=set(r)
    print(len(s))

D 修改后的和

链接: 修改后的和

1. 题目描述

在这里插入图片描述

2. 思路分析

  • 每次操作都会把这个数变0,换言之每个数只需要操作1次。而它的价值是固定的就是v*len。
  • 那么把每个操作的价值排序,从大到小取m个即可。
  • 你可能会担心操作的顺序会不会影响后续的价值,那么从后往前操作即可不会影响。

3. 代码实现

def solve():
    n, m = RI()
    a = RILST()[::-1]
    p = []
    for i, v in enumerate(a, start=1):
        if v > 0:
            p.append(v * i)
    p.sort(reverse=True)
    print(sum(a) - sum(p[:m]))

E 幼稚园的树2

链接: 幼稚园的树2

1. 题目描述

在这里插入图片描述

2. 思路分析

我仿佛在做小学奥数。
  • 对每颗树的答案单独计算,疯狂分类讨论即可。
  • 如果m天根本长不过k,那么可以直接计算。
  • 否则,先计算第一次长过k需要几天:
    • 由于必须长过k,即至少要到k+1,那么要长k+1-hi,速度是ai,用上取整公式算出第一次被剪成b的花费天数one。
  • 那么还剩p=m-1-one天可以长,从b开始。
  • 显然,每隔几天就会超过k,变成b,这个周期是per=ceil((k+1-b)/ai)。
  • 那么实际有效的天数就是p%per。
  • ans[i]=b+p*ai

3. 代码实现

#       ms
def solve():
    n,m,k,b = RI()
    h = RILST()
    a = RILST()
    ans = [0]*n
    for i,(x,y) in enumerate(zip(h,a)):
        if x + y*(m-1) <= k:
            ans[i] = x + y*(m-1)
            continue
        one = (k+1-x+y-1)//y
        p = m -1 - one   # 还能长p天
        if p == 0:
            ans[i] = b
            continue
        per = (k+1-b+y-1)//y  # 每per天会被剪到b
        p %= per
        ans[i] = b + p*y
    print(*ans)

F 最便宜的构建

链接: 最便宜的构建

1. 题目描述

在这里插入图片描述

2. 思路分析

题目很长,抓住关键词最小化最大值。
  • 二分答案。
  • 由于边不怕加多,直接尽可能的加边,则要求的集合更有可能连通。
  • 最大边越大,能加的边越多,更可能连通;最大边越小,加的边少,越不会连通;满足二段性。
  • check时,把小于mid的边全部加进并查集,然后检查每个集合的连通性即可。
  • 答案的上下界可以直接写0,1e9。也可以写min(w),max(w)

3. 代码实现

#       ms

def lower_bound(lo: int, hi: int, key):
    """由于3.10才能用key参数,因此自己实现一个。
    :param lo: 二分的左边界(闭区间)
    :param hi: 二分的右边界(闭区间)
    :param key: key(mid)判断当前枚举的mid是否应该划分到右半部分。
    :return: 右半部分第一个位置。若不存在True则返回hi+1。
    虽然实现是开区间写法,但为了思考简单,接口以[左闭,右闭]方式放出。
    """
    lo -= 1  # 开区间(lo,hi)
    hi += 1
    while lo + 1 < hi:  # 区间不为空
        mid = (lo + hi) >> 1  # py不担心溢出,实测py自己不会优化除2,手动写右移
        if key(mid):  # is_right则右边界向里移动,目标区间剩余(lo,mid)
            hi = mid
        else:  # is_left则左边界向里移动,剩余(mid,hi)
            lo = mid
    return hi


class DSU:
    """基于数组的并查集"""

    def __init__(self, n):
        self.fathers = list(range(n))
        self.size = [1] * n  # 本家族size
        self.edge_size = [0] * n  # 本家族边数(带自环/重边)
        self.n = n
        self.set_count = n  # 共几个家族

    def find_fa(self, x):
        fs = self.fathers
        t = x
        while fs[x] != x:
            x = fs[x]
        while t != x:
            fs[t], t = x, fs[t]
        return x

    def union(self, x: int, y: int) -> bool:
        x = self.find_fa(x)
        y = self.find_fa(y)

        if x == y:
            self.edge_size[y] += 1
            return False
        # if self.size[x] > self.size[y]:  # 注意如果要定向合并x->y,需要干掉这个;实际上上边改成find_fa后,按轶合并没必要了,所以可以常关
        #     x, y = y, x
        self.fathers[x] = y
        self.size[y] += self.size[x]
        self.edge_size[y] += 1 + self.edge_size[x]
        self.set_count -= 1
        return True


#       ms
def solve():
    n, m = RI()
    es = []
    for _ in range(m):
        u, v, w = RI()
        es.append((w, u - 1, v - 1))

    es.sort()
    k, = RI()
    s = []
    for _ in range(k):
        si, *ss = RI()
        s.append(ss)

    def ok(x):
        dsu = DSU(n)
        for w, u, v in es:
            if w > x: break
            dsu.union(u, v)
        for ss in s:
            p = dsu.find_fa(ss[0] - 1)
            for u in ss[1:]:
                if dsu.find_fa(u - 1) != p:
                    return False
        return True

    print(lower_bound(min(es)[0], max(es)[0], ok))

G 跳石头,搭梯子

链接: 跳石头,搭梯子

1. 题目描述

在这里插入图片描述

2. 思路分析

过是过了,排序贪心那步没证出来。
  • 一看搭梯子的条件是中间的梯子必须短于两段,那么考虑单调递减栈。
    • 单减栈出栈时,当前i是栈顶右边第一个大于栈顶的位置。
    • 入栈时,栈顶是当前i左边第一个大于i的位置。
    • 意味着中间的数都是小于两端,可以搭梯子。
      • 注意不要搭相邻的两个数。
  • 找到所有梯子,考虑用类似D题的方法,计算每个梯子的贡献和原本总花费,用总花费减去最优的m个梯子即可。
    • 如何计算贡献。
      • 显然贡献=这段的原花费-梯子花费。
      • 按贡献排序,取最大的m个梯子,但梯子不能重叠,直到取到m个梯子即可。
      • 这里不知道怎么证明,但是ac。直觉上:
        • 由于花费是abs的,因此越宽的梯子越nb,毕竟两端是超过中间的,它们天然的会排在前边。
  • 剩下的问题是怎么快速判断重叠,由于py没有有序集合,我贴了个RURQ的树状数组,它可以用log的时间操作。
    • 注意梯子两端是可以重叠的,是中间不能重叠,那么选择把左端点右移一位,正好可以给BIT用。

3. 代码实现

class BinIndexTreeRURQ:
    """树状数组的RURQ模型"""

    def __init__(self, size_or_nums):  # 树状数组,区间加区间求和,下标需要从1开始
        # 如果size 是数字,那就设置size和空数据;如果size是数组,那就是a
        if isinstance(size_or_nums, int):
            self.size = size_or_nums
            self.c = [0 for _ in range(self.size + 5)]
            self.c2 = [0 for _ in range(self.size + 5)]
        else:
            self.size = len(size_or_nums)
            self.c = [0 for _ in range(self.size + 5)]
            self.c2 = [0 for _ in range(self.size + 5)]
            for i, v in enumerate(size_or_nums):
                self.add_interval(i + 1, i + 1, v)

    def add_point(self, c, i, v):  # 单点增加,下标从1开始;不支持直接调用,这里增加的是差分数组的单点,同步修改c2
        while i <= self.size:
            c[i] += v
            i += -i & i

    def sum_prefix(self, c, i):  # 前缀求和,下标从1开始;不支持直接调用,这里求和的是差分数组的前缀和;传入c决定怎么计算,但是不要直接调用 无视吧
        s = 0
        while i >= 1:
            s += c[i]
            i -= -i & i
        return s

    def add_interval(self, l, r, v):  # 区间加,下标从1开始,把[l,r]闭区间都加v
        self.add_point(self.c, l, v)
        self.add_point(self.c, r + 1, -v)
        self.add_point(self.c2, l, (l - 1) * v)
        self.add_point(self.c2, r + 1, -v * r)

    def sum_interval(self, l, r):  # 区间求和,下标从1开始,返回闭区间[l,r]上的求和
        return self.sum_prefix(self.c, r) * r - self.sum_prefix(self.c2, r) - self.sum_prefix(self.c, l - 1) * (
                l - 1) + self.sum_prefix(self.c2, l - 1)

    def query_point(self, i):  # 单点询问值,下标从1开始,返回i位置的值
        return self.sum_prefix(self.c, i)

    def lowbit(self, x):
        return x & -x

"""
先用单调栈求出所有可以搭的桥
记录每个桥如果搭,贡献是多少,显然是 原花费-过桥的花费
把桥按贡献排序,从大到小取m个,但不能重叠
答案就是 原花费-桥的贡献
证明:请木木大佬补充
"""
#   1113ms
def solve():
    n, m = RI()
    a = RILST()
    ans = 0
    p = [0] * n  # 相邻差的前缀和
    for i in range(1, n):
        d = abs(a[i] - a[i - 1])
        ans += d
        p[i] = d + p[i - 1]
    # print(p)
    st = []
    lines = []
    for i, v in enumerate(a):
        while st and a[st[-1]] < v:
            j = st[-1]
            if j + 1 < i:
                lines.append((abs(v - a[j]) - (p[i] - p[j]), j, i))  # j~i可以搭梯子
            st.pop()
        if st and st[-1] + 1 < i:
            j = st[-1]
            if j + 1 < i:
                lines.append((abs(v - a[j]) - (p[i] - p[j]), j, i))  # j~i可以搭梯子
        st.append(i)
    lines.sort()
    tree = BinIndexTreeRURQ(n)
    for w, l, r in lines:
        if not m:
            break
        if tree.sum_interval(l + 1, r) == 0:
            ans += w
            m -= 1
        tree.add_interval(l + 1, r, 1)

    # print(lines)
    print(ans)

六、参考链接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/629528.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一分钟学一个 Linux 命令 - tar

前言 大家好&#xff0c;我是 god23bin。今天给大家带来的是 Linux 命令系列&#xff0c;每天只需一分钟&#xff0c;记住一个 Linux 命令不成问题。今天&#xff0c;我们要介绍的是一个常用且强大的命令&#xff1a;tar。 什么是 tar 命令&#xff1f; tar 是 tape archive…

C语言经典题目(三)

C站的小伙伴们&#xff0c;大家好呀&#xff01;&#x1f60a;&#x1f60a;✨✨这一篇是C语言之经典题目篇&#xff0c;除程序设计&#xff0c;还有一些不错的程序分析&#xff0c;快来和我一起进入C语言的世界吧&#xff01;✨✨✨ &#x1f495;C语言其他刷题篇在这里哦&…

【Python程序设计】——重点题目(期末不挂科)

课本&#xff1a; 目录 &#x1f552; 1. 控制结构&#x1f552; 2. 数据类型&#x1f552; 3. 函数&#x1f552; 4. 文件操作&#x1f552; 5. 面向对象&#x1f552; 6. Excel操作&#x1f552; 7. 实验课题目合集&#x1f552; 8. 思政题 &#x1f552; 1. 控制结构 【例…

chatgpt赋能python:Python怎么二次安装?

Python怎么二次安装&#xff1f; 介绍 Python作为一种广泛应用的编程语言&#xff0c;其安装也是极其简单。只需要在Python官网上下载对应版本的安装包&#xff0c;并按照提示进行安装即可。但是&#xff0c;如果你需要二次安装Python&#xff0c;比如更新到新的版本或者将Py…

百度、头条、360、搜狗下拉拓词及长尾关键词挖掘-批量多线程

百度、头条、360、搜狗下拉拓词及长尾关键词挖掘软件介绍&#xff1a; 1、在如今竞争激烈的互联网时代&#xff0c;作为SEO站长&#xff0c;我们都知道一个事实&#xff1a;流量就是金钱&#xff01;而要想在海量信息中脱颖而出&#xff0c;我们需要借助一些强大的工具来帮助我…

OpenMMLab-AI实战营第二期——4-1.目标检测与MMDetection

文章目录 1. 目标检测的基本范式1.0-1 目标检测简介1.0-2 基本概念1.1 滑窗1.1.1 滑窗基本思想1.1.2 滑窗效率问题改进1.1.3 感受野计算 1.2-1 使用卷积实现密集预测1.2.1 在特征图上进行密集预测1.2.2 边界框回归1.2.3 非极大值抑制&#xff08;Non-Maximum Suppression&#…

chatgpt赋能python:Python入门:如何下载和安装JupyterNotebook

Python入门&#xff1a;如何下载和安装Jupyter Notebook Jupyter Notebook是Python编程必备的工具之一&#xff0c;它可以帮助你快速地编写和测试Python代码。在这篇文章中&#xff0c;我们将向你展示如何下载和安装Jupyter Notebook。如果你是一名Python入门者&#xff0c;这…

神经网络:CNN中的filter,kernel_size,strides,padding对输出形状的影响

输入数据在经过卷积层后&#xff0c;形状一般会发生改变&#xff0c;而形状的变化往往与以下四个超参数有关。 1&#xff0c;filter&#xff08;out_channel&#xff09; 该超参数控制着输入数据经过卷积层中需要与几个卷积核进行运算&#xff0c;而输入数据与每个卷积核进行…

【P57】JMeter 保存响应到文件(Save Responses to a file)

文章目录 一、保存响应到文件&#xff08;Save Responses to a file&#xff09;参数说明二、准备工作三、测试计划设计 一、保存响应到文件&#xff08;Save Responses to a file&#xff09;参数说明 可以将结果树保存到文件 使用场景&#xff1a;当结果太大&#xff0c;使…

Mybatis插件001分页 pagehelper

Mybatis-PageHelper/Important.md at master pagehelper/Mybatis-PageHelper GitHubMybatis通用分页插件. Contribute to pagehelper/Mybatis-PageHelper development by creating an account on GitHub.https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis…

短视频社区的商业化和流量分发

商业化本质上是一门流量生意&#xff0c;那么为什么要做流量&#xff1f; 1、流量分配影响社区生态 一个社区的总流量是要在三类流量里面做分配&#xff0c;此消彼长&#xff1a; 私域流量公域流量&#xff08;中心化运营 算法推荐&#xff09;商业化的流量&#xff08;也是…

chatgpt赋能python:Python代码的保存:保障开发效率和代码质量

Python 代码的保存&#xff1a;保障开发效率和代码质量 Python 是一种高级语言&#xff0c;被广泛应用于数据分析、机器学习、 Web 开发等各个领域。它的语法简洁、易于学习&#xff0c;拥有丰富的标准库和第三方库&#xff0c;帮助开发者快速实现功能。在这样一个代码生产效率…

[ruby on rails] passenger+nginx 部署rails

安装Passenger 方法1 Passenger 是一个 app server&#xff0c;支持基于 Rack 框架的 Ruby app&#xff08;包括 Rails&#xff09;&#xff0c;作为模块变异到Nginx&#xff0c;不需要自己启动。 安装 Passenger 最简单的方法是通过 apt 安装&#xff0c;首先导入 Passenger…

英语4级技巧

真题链接&#xff1a;https://pan.baidu.com/s/1IZ0MmEpkANUm77ZLDmHs1A?pwd1111 提取码&#xff1a;1111 一、听力技巧 听到什么选什么 听发音 4级 90% 6级 60% 1、开头原则 2、顺序原则 1、单词发音/语音现象&#xff08;连读、弱读、失去爆破&#xff09; 反转词&#…

chatgpt赋能python:Python如何产生随机整数?

Python如何产生随机整数&#xff1f; Python是一种高级编程语言。它允许程序员轻松地创建各种类型的应用程序&#xff0c;包括生成随机整数。本文将介绍如何在Python中使用内置的随机数函数来生成随机整数。 random模块 Python中的random模块提供了生成随机数的函数。这些函…

chatgpt赋能python:Python实现二分查找

Python实现二分查找 在计算机科学中&#xff0c;二分查找是一种在有序数组中查找特定值的算法。 以一个有序数组为例&#xff0c;二分查找从数组的中间元素开始查找。如果需要查找的值与中间元素相同&#xff0c;则返回中间元素的位置。否则&#xff0c;如果查找的值比中间元…

ubuntu 20.04 aarch64 平台交叉编译 glib

glib 是什么&#xff1f; glib 是一个比较强大的 软件库&#xff0c;类似于 libc 库 交叉编译 当前需要移植到 aarch64&#xff08;ARM64&#xff09;平台上&#xff0c;需要使用 aarch64 交叉编译工具链编译 glib 环境准备 ubuntu 20.04 安装较新版本的 meson &#xff1…

使用大型语言模(LLM)构建系统(三):思维链推理

今天我学习了DeepLearning.AI的 Building Systems with LLM 的在线课程&#xff0c;我想和大家一起分享一下该门课程的一些主要内容。 下面是我们访问大型语言模(LLM)的主要代码&#xff1a; import openai#您的openai的api key openai.api_key YOUR-OPENAI-API-KEY def get_…

vue3中的插槽

目录 什么是插槽插槽的类型默认插槽具名插槽作用域插槽 插槽的默认内容动态组件中使用插槽插槽的组合使用插槽的高级用法插槽复用将动态组件作为插槽 插槽的优先级规则 什么是插槽 插槽是组件中用来承载内容的一种机制&#xff0c;可以让组件在运行时接受来自其它组件的任意内…

【后端面经-数据库】MySQL的存储引擎简介

【后端面经-数据库】MySQL的存储引擎简介 MySQL的存储引擎0. 存储引擎的查看和修改1. MyISAM2. InnoDB3. MEMORY4. MERGE5. 总结6. 参考博客 MySQL的存储引擎 mysql主要有四类存储引擎&#xff0c;目前主要使用InnoDB作为存储引擎。 0. 存储引擎的查看和修改 查看当前数据库…