[牛客复盘] 牛客小白月赛70 20230407

news2024/9/25 1:24:27

[牛客复盘] 牛客小白月赛70 20230407

    • 一、本周周赛总结
    • A、 小d和答案修改
      • 2. 思路分析
      • 3. 代码实现
    • B、小d和图片压缩
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • C、小d和超级泡泡堂
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • D、小d和孤独的区间
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • E、小d的博弈
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • F、小d和送外卖
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • 六、参考链接

一、本周周赛总结

  • 第一次打小白月赛,据说比较简单,但还是有两道没做出来。
  • A 模拟。
  • B 模拟。
  • C FloodFill。
  • D 前缀和+哈希。
  • E 博弈 打表/贪心。
  • F 树上背包/有依赖的背包,注意卡常。

在这里插入图片描述

A、 小d和答案修改

在这里插入图片描述

2. 思路分析

按题意模拟即可。

3. 代码实现

import sys

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


#       ms
def solve():
    n, m = RI()
    g = []
    for _ in range(n):
        g.append(RILST())
    for i in range(0, n, 2):
        for j in range(0, m, 2):
            c = (g[i][j] + g[i + 1][j] + g[i + 1][j + 1] + g[i][j + 1]) // 4
            print(c, end=' ')
        print()


if __name__ == '__main__':
    solve()

B、小d和图片压缩

链接: 小d和图片压缩

1. 题目描述

在这里插入图片描述

2. 思路分析

模拟。

3. 代码实现

def solve():
    n, m = RI()
    g = []
    for _ in range(n):
        g.append(RILST())
    for i in range(0, n, 2):
        for j in range(0, m, 2):
            c = (g[i][j] + g[i + 1][j] + g[i + 1][j + 1] + g[i][j + 1]) // 4
            print(c, end=' ')
        print()

C、小d和超级泡泡堂

链接: 小d和超级泡泡堂

1. 题目描述

在这里插入图片描述

2. 思路分析

  • floodfiill的时候计数路上遇到的草即可。
  • 注意访问后把位置变成石头防止重复访问。

3. 代码实现

def solve():
    n, m = RI()
    g = []
    start = (0, 0)
    for i in range(n):
        s, = RS()
        g.append(list(s))
        if '@' in s:
            j = s.index('@')
            start = (i, j)
            g[i][j] = '#'
    ans = 0
    q = deque([start])
    while q:
        x, y = q.popleft()
        for a, b in (x - 1, y), (x + 1, y), (x, y + 1), (x, y - 1):
            if 0 <= a < n and 0 <= b < m and g[a][b] != '#':
                if g[a][b] == '!':
                    ans += 1
                g[a][b] = '#'
                q.append((a, b))
    print(ans)

D、小d和孤独的区间

链接: 小d和孤独的区间

1. 题目描述

在这里插入图片描述

2. 思路分析

  • 典中典中典,题目中只包含01甚至是没用的。
  • 计算前缀和,遍历的时候用哈希表记录每个前缀和出现的次数。
  • 当遍历到i时,s[i]-t = 1,t = s[i]-1,找到前边有几个t,则以i为右端点的合法区间就有几个。

3. 代码实现

def solve():
    n, = RI()
    a = RILST()
    p = Counter([0])
    s = ans = 0
    for v in a:
        s += v
        ans += p[s - 1]
        p[s] += 1
    print(ans)      

E、小d的博弈

链接: 小d的博弈

1. 题目描述

在这里插入图片描述

2. 思路分析

  • 看到博弈上来就写了个记忆化搜索,很快啊 ,就TLE了。代码如下,看状态数和nm的范围显然要T:
@lru_cache(None)
def dfs(m, n):
    if m <= 2 and n <= 2:
        return False
    if m <= 2 or n <= 2:
        return True
    for i in range(1, (m + 1) // 2):
        if not dfs(i, n):
            return True
    for j in range(1, (n + 1) // 2):
        if not dfs(m, j):
            return True
    return False
  • 把这个表打出来,形如(注意是nm从1开始):
    -在这里插入图片描述
  • 看这美妙的规律,2,、4、8…的增长似乎代表着什么,每次增长2的幂,那么发现把这个数+1,求二进制长度,俩数二进制长度相同,bob就赢,否则alice赢。(对应代码里solve)

  • 不按规律做题的话,其实是把每条边以最大次数切割,看看分别能切多少次,如果两边次数相同,则bob赢。对应代码里solve1
  • 这是因为:bob总可以按照alice的切法,使切完后依然边数相同,那么bob必是切最后一刀的。

3. 代码实现

# Problem: 小d的博弈
# Contest: NowCoder
# URL: https://ac.nowcoder.com/acm/contest/53366/E
# Memory Limit: 524288 MB
# Time Limit: 2000 ms

import sys
from functools import lru_cache

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

MOD = 10 ** 9 + 7
PROBLEM = """
"""


@lru_cache(None)
def dfs(m, n):
    if m <= 2 and n <= 2:
        return False
    if m <= 2 or n <= 2:
        return True
    for i in range(1, (m + 1) // 2):
        if not dfs(i, n):
            return True
    for j in range(1, (n + 1) // 2):
        if not dfs(m, j):
            return True
    return False


#     603  ms
def solve1():
    n, m = RI()
    y = x = 0
    while n > 2:
        n = (n - 1) // 2
        x += 1
    while m > 2:
        m = (m - 1) // 2
        y += 1
    if x != y:
        print('Alice')
    else:
        print('Bob')


#   573    ms
def solve():
    n, m = RI()

    if (n + 1).bit_length() != (m + 1).bit_length():
        print('Alice')
    else:
        print('Bob')


if __name__ == '__main__':
    t, = RI()
    for _ in range(t):
        solve()
    # for i in range(1,40):
    #     for j in range(1,40):
    #         print(int(dfs(i,j)), end=' ')
    #     print()     

F、小d和送外卖

链接: 小d和送外卖

1. 题目描述

在这里插入图片描述

2. 思路分析

  • 这是我第二次做树形背包,第一次还是做acw10有依赖的背包。不同在于:
    • acw10是必须选父节点才能选子节点。那么向下递归之前先把父节点选上,更新dp数组,且向下传递时,背包容量减小。
    • 本题是必须选子节点才能选父节点。需要先处理子树后,再尝试把整颗子树包括父节点一起选上。

  • 看到m<=50的份数就可以想到背包了。这里做一下转化:选择取消哪m份外卖能使总距离和最短 等价与 :选择取消哪m份外卖能使节省的总距离和最长。
  • 转换后,只需要考虑子树即可。当然,前提是先计算出不取消的话需要跑的总距离。
  • 可以先用一个dfs后根遍历计算出每颗子树里,包含几个外卖订单,用yes[i]表示;同时,如果跑完子树里所有订单,需要走的节点数,用cnt[i]表示。
  • 我们发现,需要走的路程=边数*2=(节点数-1)*2
  • 接下来,只需要计算出选m个订单取消,可以最多少走多少个节点即可。用树形背包解决。
    • 对每个子树,分别定义f = [0] + [-inf] * m,其中f[i]表示在这颗子树下,取消i个订单,最多少走几个节点。dfs结束后返回f。
    • 我们dfs u的每个子树v,令p=dfs(v),根据定义,p是v子树取消i订单的每种情况,而这颗子树我们可以选p里的任意一种情况或不选。那么p对于u来说就是一个分组背包的一个组。遍历每个子树作为物品更新f即可。
    • 用完子树后,尝试是否可以把u这颗子树整个拿掉,前提是这颗子树里的订单yes<=m,更新f[yes]=cnt,即取消yes个订单,少走个子树的节点。背包转移就结束了。
    • 最后省的最大值就是max§。这里由于是后根遍历,每次计算完都是进父节点用,直接用一个全局遍历储存一个,滚动赋值即可。
  • 最后答案是(cnt[0] - 1 - max(p)) * 2。即根节点的原本路程-省的路程。

  • 吐槽卡常,背包转移时如果不提前break会TLE。
  • 另外我试图写了bfs版本,先根遍历顺序后,逆序处理。会更慢一些。猜测是因为:由于计算时不能保证子树处理完了立马给父节点用,因此需要全局储存每个子树的f,内存会用的多些。

3. 代码实现

# Problem: 小d和送外卖
# Contest: NowCoder
# URL: https://ac.nowcoder.com/acm/contest/53366/F
# Memory Limit: 524288 MB
# Time Limit: 2000 ms

import sys
from collections import deque
from math import inf
from types import GeneratorType

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

MOD = 10 ** 9 + 7
PROBLEM = """
"""


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


#    1455   ms
def solve1():
    n, m = RI()
    g = [[] for _ in range(n)]
    for _ in range(n - 1):
        u, v = RI()
        u -= 1
        v -= 1
        g[u].append(v)
        g[v].append(u)
    k, = RI()
    a = RILST()
    if k <= m:
        return print(0)
    s = set(x - 1 for x in a)
    # print(s)
    cnt = [0] * n  # 如果要送完这个子树的所有订单,要访问多少个节点;答案是边数*2,即(cnt[i]-1)*2
    yes = [0] * n  # 每个子树下共有几个订单

    p = []  # 子树的分组背包,p[i]代表如果这个子树里退i个单,最多能省几个需要访问的节点

    @bootstrap
    def dfs(u, fa):
        f = [0] + [-inf] * m  # 当前子树如果一个都不退,就不能省节点
        yes[u] = int(u in s)  # 如果本节点有订单,则订单数+1
        for v in g[u]:
            if v == fa: continue
            yield dfs(v, u)

            if yes[v]:  # 如果子树有订单,要累计过来,且路过的节点也要累计
                yes[u] += yes[v]
                cnt[u] += cnt[v]

            for j in range(m, 0, -1):
                for v, w in enumerate(p):
                    if v <= j:
                        f[j] = max(f[j], f[j - v] + w)
                    else:
                        break

        if yes[u]:  # 如果这个子树有订单,则这个加上这个节点
            cnt[u] += 1

        if yes[u] <= m:  # 如果这个子树下的所有订单不超过m,则可以尝试剪掉整个子树。
            f[yes[u]] = cnt[u]
        p[:] = f[:]
        yield

    dfs(0, -1)
    # print(cnt)
    # print(yes)

    print((cnt[0] - 1 - max(p)) * 2)


#     1447ms  ms
def solve2():
    n, m = RI()
    g = [[] for _ in range(n)]
    for _ in range(n - 1):
        u, v = RI()
        u -= 1
        v -= 1
        g[u].append(v)
        g[v].append(u)
    k, = RI()
    a = RILST()
    if k <= m:
        return print(0)
    s = set(x - 1 for x in a)
    # print(s)
    cnt = [0] * n  # 如果要送完这个子树的所有订单,要访问多少个节点;答案是边数*2,即(cnt[i]-1)*2
    yes = [0] * n  # 每个子树下共有几个订单

    @bootstrap
    def dfs(u, fa):
        yes[u] = int(u in s)
        for v in g[u]:
            if v == fa: continue
            yield dfs(v, u)
            if yes[v]:
                yes[u] += yes[v]
                cnt[u] += cnt[v]
        if yes[u]:
            cnt[u] += 1

        yield

    dfs(0, -1)
    # print(cnt)
    # print(yes)
    p = []

    @bootstrap
    def dfs2(u, fa):
        f = [0] + [-inf] * m
        for v in g[u]:
            if v == fa: continue
            yield dfs2(v, u)
            for j in range(m, 0, -1):
                for v, w in enumerate(p):
                    if v <= j:
                        f[j] = max(f[j], f[j - v] + w)
                    else:
                        break
        if yes[u] <= m:
            f[yes[u]] = cnt[u]
            # print(u, f)
        p[:] = f[:]
        yield

    dfs2(0, -1)
    print((cnt[0] - 1 - max(p)) * 2)


#       ms
def solve():
    n, m = RI()
    g = [[] for _ in range(n)]
    for _ in range(n - 1):
        u, v = RI()
        u -= 1
        v -= 1
        g[u].append(v)
        g[v].append(u)
    k, = RI()
    a = RILST()
    if k <= m:
        return print(0)
    s = set(x - 1 for x in a)
    # print(s)
    cnt = [0] * n  # 如果要送完这个子树的所有订单,要访问多少个节点;答案是边数*2,即(cnt[i]-1)*2
    yes = [0] * n  # 每个子树下共有几个订单

    pp = [[] for _ in range(n)]
    fas = [-1] * n
    order = []
    q = deque([0])
    while q:
        u = q.popleft()
        order.append(u)
        for v in g[u]:
            if v == fas[u]: continue
            fas[v] = u
            q.append(v)

    for u in order[::-1]:
        yes[u] = int(u in s)
        f = [0] + [-inf] * m
        for v in g[u]:
            if v == fas[u]: continue
            if yes[v]:
                yes[u] += yes[v]
                cnt[u] += cnt[v]
            p = pp[v]
            for j in range(m, 0, -1):
                for v, w in enumerate(p):
                    if v <= j:
                        f[j] = max(f[j], f[j - v] + w)
                    else:
                        break
        if yes[u]:
            cnt[u] += 1
        if yes[u] <= m:
            f[yes[u]] = cnt[u]
        pp[u] = f

    print((cnt[0] - 1 - max(pp[0])) * 2)


if __name__ == '__main__':
    solve()  

六、参考链接

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

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

相关文章

C语言内存函数介绍以及实现

目录 前言 一:内存拷贝函数 (1)memcpy( )函数 (2)memove( )函数 二:内存比较函数 三:内存设置函数 前言 本文介绍的函数的函数声明都在头文件string.h中。 一:内存拷贝函数 (1)memcpy( )函数 函数声明&#xff1a;void* memcpy(void* dest,const void* src,size_t num) 作用…

【python】制作一个简单的界面,有手就行的界面~

目录前言准备工作试手小案例开始我们今天的案例教学尾语 &#x1f49d;前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! ttkbootstrap 是一个基于 tkinter 的界面美化库&#xff0c; 使用这个工具可以开发出类似前端 bootstrap 风格的 tkinter 桌面程序。 ttkbootstrap 不…

8:00面试,8:05就出来了 ,问的实在是太变态了···

从外包出来&#xff0c;没想到算法死在另一家厂子。 自从加入这家公司&#xff0c;每天都在加班&#xff0c;钱倒是给的不少&#xff0c;所以也就忍了。没想到12月一纸通知&#xff0c;所有人不许加班&#xff0c;薪资直降30%&#xff0c;顿时有吃不起饭的赶脚。 好在有个兄弟…

Yolov5_DeepSort_Pytorch:基于 Yolov5 + Deep Sort 的实时多目标跟踪器

Yolov5_DeepSort_Pytorch&#xff1a;基于 Yolov5 Deep Sort 的实时多目标跟踪器 原创 视界君 Python视界 昨天 Python视界分享 原文地址&#xff1a;Yolov5_DeepSort_Pytorch&#xff1a;基于 Yolov5 Deep Sort 的实时多目标跟踪器 简介 该存储库包含一个两阶段跟踪器。…

linux主机设置主机间免密登录

举例&#xff1a;想要在A主机免密登录到B主机&#xff1b; 此文案前提是linux都安装了ssh服务&#xff0c;可以使用systemctl status sshd 查看ssh状态 1、使用任意用户在A主机上执行ssh-keygen -t rsa 所有提示均按回车默认&#xff0c;会在当前目录生成.ssh文件夹&#xff0…

实战-高并发下的读/写

文章目录高并发下的读/写高并发读业务场景高并发写业务场景同时高并发读和高并发写业务场景高并发读策略一&#xff1a;加缓存/读副本方案一&#xff1a;本地缓存/集中式缓存方案二&#xff1a;数据库层面的改变&#xff0c;Master/Slave&#xff0c;使用主从完成读写分离方案三…

MySQL学习笔记:count(1)、count(*)、count(字段)的区别

关于数据库中行数统计&#xff0c;无论是MySQL还是Oracle&#xff0c;都有一个函数可以使用&#xff0c;那就是COUNT&#xff08;&#xff09;。 但是&#xff0c;就是这个常用的COUNT函数&#xff0c;却暗藏着很多玄机&#xff0c;尤其是在面试的时候&#xff0c;一不小心就会…

JUC多并发编程 CompletableFuture

Future 接口理论 Future 接口(FutureTask 实现类)&#xff1a; 定义了操作异步任务执行一些方法&#xff0c;如获取异步任务的执行结果、取消任务的执行、判断任务是否被取消、判断任务执行是否完毕等 方法图&#xff1a; 类图&#xff1a; 代码示例&#xff1a; import ja…

Maven聚合开发【实例详解---5555字】

目录 一、Maven聚合开发_继承关系 二、Maven聚合案例 1. 搭建dao模块 2. 搭建service模块 3. 搭建web模块 4. 运行项目 一、Maven聚合开发_继承关系 Maven中的继承是针对于父工程和子工程。父工程定义的依赖和插件子工程可以直接使用。注意父工程类型一定为POM类型工程…

数字电路学习笔记 门电路概述

1 高低电平的实现 在数字电路中&#xff0c;输入输出都是二值逻辑&#xff0c;其高低电平用“0”和“1”表示其高低电平的获得是通过开关电路来实现&#xff0c;如二极管或三极管电路组成。如图 高低电平实现原理电其原理电路 当开关 S 断开时&#xff0c;输出电压 v。 V。&am…

Alibaba开源的Java诊断工具Arthas-实战

目录参考一、启动二、支持的ognl表达式三、监听参数监听Controller 的参数和返回值监听完整参数和返回值监听kafka消费监听单个参数监听异常按照耗时进行过滤监听参数比较四、变量和方法查询静态成员变量值查询配置类具体属性的值通过类加载器查看Spring容器中对象所有属性执行…

Qt显示数学公式

文章目录一、前言二、效果展示三、库文件四、使用教程五、MathML语法5.1、顶层元素5.2、字符/符号元素5.3、通用布局元素5.4、边标和角标元素5.5、表格教学5.6、数学符号六、转换工具6.1、手写转换公式工具myscript6.2、截图转换公式工具Mathpix一、前言 目前项目中需要显示数…

MySQL数据库学习——约束——概述+演示

我们先创建一个表&#xff1a; create database itheima; use itheima; create table user(id int primary key auto_increment comment 主键, name varchar(10) not null unique comment 姓名,age int check ( age > 0 && age <120 ) comment 年龄,status char…

零代码是什么?零代码平台适合谁用?

随着信息技术的发展&#xff0c;软件开发领域也不断发生变革&#xff0c;零代码&#xff08;No-Code&#xff09;开发模式越来越受到关注。 零代码到底是什么&#xff0c;能不能用通俗的话来说&#xff1f;这就来给大家讲一讲&#xff01; 01 零代码为什么出现&#xff1f; 随…

spring cloud consul服务注册源码分析

我们注册在consul上的服务&#xff0c;都是通过spring cloud consul discorvery来实现的&#xff0c;可以通过maven依赖导入spring-cloud-consul-discovery包。 对于spring项目&#xff0c;首先查看spring.factories文件&#xff1a; 从源码中可以找到服务注册、自动服务注册…

kubespray v2.21.0 部署 kubernetes v1.24.0 集群

文章目录1. 前言2. 创建7台虚拟机3. 部署 git3.1 dnf 安装3.2 tar 安装4. 下载 kubespray 介质5. 配置 zsh 终端6. 配置互信7. 安装 docker-ce8. 安装 ansible9. 安装其他依赖10. 配置内核参数11. 安装 k8s利用官方默认镜像部署 k8s 集群利用自定义构建镜像部署 k8s 集群12. 配…

第二讲 第一个Python程序

在上一课中&#xff0c;我们对 Python 语言的过去现在有了一些了解&#xff0c;我们准备好了运行 Python 程序所需要的解释器环境。相信大家已经迫不及待的想开始自己的 Python 编程之旅了&#xff0c;但是新问题来了&#xff0c;我们应该在什么地方书写 Python 程序&#xff0…

mvn测试执行用例的常用的命令

mvn执行指定的测试用例 mvn常用的命令 mvn mvn test -Dtestxxx&#xff1a;执行指定测试用例的命令&#xff0c;后面的xxx就是指定的所有被标记的用例 mvn test -Denv环境名 -Dtest包的路径.*:指定具体的某个环境的某个包下的所用例 mvn test -Dgroupsxxx -Dtestxxx :指定某…

Python实战案例:采集P站数据内容

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 开发环境&#xff1a; Python 3.8 / 编译器 Pycharm 2021.2版本 / 编辑器 模块使用&#xff1a; requests &#xff1a; 主要用来发 送 HTTP 请求 、 属于第三方模块 parsel &#xff1a; 解析html&#xff0c;xml内…

业务高峰期,人力需求突增,灵活用工成破局关键

在上一篇文章里&#xff0c;讲到了盖雅零工平台如何帮助HR管理复杂、灵活的零工人员。 而零工平台是否好用&#xff0c;不仅要便于HR管理零工&#xff0c;更需要终端的业务管理者觉得方便、实用、操作顺畅。 由于零工主要被用来解决突增的、巅峰期的、季节性的用工需求&#…