牛客小白月赛96 解题报告 | 珂学家


前言

alt


题解


A. 最少胜利题数

签到

n1 = len(set(input()))
n2 = len(set(input()))

if n1 < n2:
    n1, n2 = n2, n1

print (-1 if n1 == 6 else n1 - n2 + 1)

B. 最少操作次数

思路: 分类讨论

只有-1,0,1,2这四种结果

特判 0+1+, 1+0+

n = int(input())
s = input()

# 枚举
from collections import Counter

cnt = Counter(s)

if cnt['0'] == cnt['1']:
    if s[0:(n//2)] == "0" * (n//2) or s[0:(n//2)] == "1" * (n//2):
        print (-1)
    else:
        print (2)
elif cnt['0'] == n or cnt['1'] == n:
    print (0)
else:
    print (1)

C. 最多数组数量

思路: 双指针

枚举第一个和第二个数组的分割点x

然后找第二个和第三个数组的分割点y

找到y点后,往右移动的点都满足需求

很典的题,应该还有其他的解法

n = int(input())

arr = list(map(int, input().split()))

# 双指针
res = 0
j = 0
s1, s2 = 0, 0
s = sum(arr)
for i in range(n - 2):
    s1 += arr[i]
    while j <= i:
        s2 += arr[j]
        j += 1
    while (j < n and (s2 - s1 <= s1 or s2 - s1 <= s - s1 - (s2 - s1))):
        s2 += arr[j]
        j += 1
    if j < n:
        res += (n - j)
        
print (res)

D. 最小连通代价

思路: 分类讨论

非常好的一道题,分别讨论ab的正负

因为要尽量小,所以负值为完全图,正值维护最简单的树结构

  • 完全图
  • 树形图

ab都为正数时,其大小关系也需要在讨论下

t = int(input())

def solve():
    n, a, b = list(map(int, input().split()))
    arr = list(map(int, input().split()))
    
    n1 = sum([1 for v in arr if v % 2 == 0])
    n2 = sum([1 for v in arr if v % 2 != 0])

    res = 0
    if a <= 0 and b <= 0:
        res += n1 * (n1 - 1) // 2 * a
        res += n2 * (n2 - 1) // 2 * a
        res += n1 * n2 * b
    elif a <= 0:
        res += n1 * (n1 - 1) // 2 * a
        res += n2 * (n2 - 1) // 2 * a
        if n1 > 0 and n2 > 0:
            res += b
    elif b <= 0:
        if n1 > 0 and n2 > 0:
            res = n1 * n2 * b
        elif n1 > 0:
            res = (n1 - 1) * a
        elif n2 > 0:
            res = (n2 - 1) * a
    else:
        if b <= a:
            if n1 > 0 and n2 > 0:
                res = (n1 + n2 - 1) * b
            elif n1 > 0:
                res = (n1 - 1) * a
            elif n2 > 0:
                res = (n2 - 1) * a
        else:
            if n1 > 0:
                res += (n1 - 1) * a
            if n2 > 0:
                res += (n2 - 1) * a
            if n1 > 0 and n2 > 0:
                res += b
    print (res)
    
for _ in range(t):
    solve()

E. 最大稳定数值

思路: 树上DFS + 名次树(离散化+数状数组/动态开点的线段树)

对于某个节点,祖先的前缀和不会变,但是子孙的和会变小

根据定义,节点会因为子树的删边而成为满足要求

这些点具备如下特点

  • 祖先节点前缀和大于等于该节点
  • 该节点大于子树节点和

可以称这些节点为候选节点

然后从删边寻求突破口

删边会影响祖先节点集的子树和,能否快速统计影响个数呢? 删边会影响祖先节点集的子树和,能否快速统计影响个数呢? 删边会影响祖先节点集的子树和,能否快速统计影响个数呢?

或者说挪动某个范围,统计满足条件的个数 或者说挪动某个范围,统计满足条件的个数 或者说挪动某个范围,统计满足条件的个数

这种一般采用,名次树/树状数组/线段树来快速计算

所以大致的思路为

  • 自底向上DFS,统计子树和和祖先前缀和
  • 自顶向下DFS,利用名次树统计变更节点数

这样两次DFS即可,时间复杂度为 O ( n ) O(n) O(n)

import java.io.BufferedInputStream;
import java.util.*;

public class Main {

    static class BIT {
        int n;
        int[] arr;
        public BIT(int n) {
            this.n = n;
            this.arr = new int[n + 1];
        }
        int query(int p) {
            int res = 0;
            while (p > 0) {
                res += arr[p];
                p -= p & -p;
            }
            return res;
        }
        void update(int p, int d) {
            while (p <= n) {
                this.arr[p] += d;
                p += p & -p;
            }
        }
    }

    static
    public class Solution {
        int n;
        int[] arr;
        List<Integer>[]g;

        long[] up;
        long[] down;

        int[] cs;

        Map<Long, Integer> idMap = new HashMap<>();
        BIT bit;

        public int solve(int n, int[] arr, int[] pa) {
            this.n = n;
            this.arr = arr;

            this.up = new long[n];
            this.down = new long[n];
            this.cs = new int[n];

            this.g = new List[n];
            Arrays.setAll(g, x->new ArrayList<>());
            for (int i = 0; i < n; i++) {
                if (pa[i] != -1) {
                    g[pa[i]].add(i);
                }
            }
            dfs(0, -1, 0);

            TreeSet<Long> ids = new TreeSet<>();
            for (int i = 0; i < n; i++) {
                if (up[i] - arr[i] >= arr[i] && down[i] - arr[i] > arr[i]) {
                    ids.add(down[i] - 2l * arr[i]);
                }
                ids.add(down[i]);
            }
            int ptr = 1;
            for (long k: ids) {
                idMap.put(k, ptr++);
            }
            this.bit = new BIT(ids.size());

            dfs3(0, -1);
            return gAns + cs[0];
        }

        int gAns = 0;

        void dfs3(int u, int fa) {
            int idx = idMap.get(down[u]);
            int r = bit.query(idx);
            r -= cs[u];
            if (r > gAns) {
                gAns = r;
            }

            if (up[u] - arr[u] >= arr[u] && down[u] - arr[u] > arr[u]) {
                bit.update(idMap.get(down[u] - arr[u] * 2l), 1);
            }

            for (int v: g[u]) {
                if (v == fa) continue;
                dfs3(v, u);
            }
            if (up[u] - arr[u] >= arr[u] && down[u] - arr[u] > arr[u]) {
                bit.update(idMap.get(down[u] - arr[u] * 2l), -1);
            }
        }

        void dfs(int u, int fa, long pre) {
            up[u] = pre + arr[u];
            down[u] += arr[u];
            for (int v: g[u]) {
                if (v == fa) continue;
                dfs(v, u, up[u]);
                down[u] += down[v];
                cs[u] += cs[v];
            }
            if (up[u] - arr[u] >= arr[u] && down[u] - arr[u] <= arr[u]) {
                cs[u] += 1;
            }
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(new BufferedInputStream(System.in));
        int n = sc.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++) {
            arr[i] = sc.nextInt();
        }
        int[] pa = new int[n];
        for (int i = 0; i < n; i++) {
            pa[i] = sc.nextInt() - 1;
        }
        Solution solution =new Solution();
        System.out.println(solution.solve(n, arr, pa));
    }

}

F. 最少逆序对数

这题的思路可以分为两层

  1. 求一个固定长度的数组,其逆序对最小为多少
  2. 如何解决数组递增的问题

先来解决第一个问题

前置准备,令

f ( a i ) 为数组中大于 a i 的个数 f(a_i)为数组中大于a_i的个数 f(ai)为数组中大于ai的个数
g ( a i ) 为数组中小于 a i 的个数 g(a_i)为数组中小于a_i的个数 g(ai)为数组中小于ai的个数

在一个数组中arr,移动一次的代价为

image.png

h ( a 0 ) = f ( a 0 ) − g ( a 0 ) h(a_0) = f(a_0) - g(a_0) h(a0)=f(a0)g(a0)

显然这题等价转换后,找到一个j,使得

S ( a ) = m i n ∑ i = 0 i = j h ( a i ) , 0 ≤ j < n S(a) = min \sum_{i=0}^{i=j} h(a_i), 0\le j \lt n S(a)=mini=0i=jh(ai),0j<n


那这题的难点就在于,

如何快速的求解 f ( a i ) , g ( a i ) 如何快速的求解f(a_i), g(a_i) 如何快速的求解f(ai),g(ai)

引入迭代的思维

假设 a r r [ 0 : i ] 子数组,其每个元素的 f i ( a j ) , g i ( a j ) 已维护,那尾巴新增一个元素 a r r [ i + 1 ] ,此时会变化什么呢? arr[0:i]子数组,其每个元素的f_i(a_j), g_i(a_j)已维护,那尾巴新增一个元素arr[i+1],此时会变化什么呢? arr[0:i]子数组,其每个元素的fi(aj),gi(aj)已维护,那尾巴新增一个元素arr[i+1],此时会变化什么呢?,

f i + 1 ( a j ) , g i + 1 ( a j ) 的更新只需要 O ( 1 ) 代价 f_{i+1}(a_j), g_{i+1}(a_j)的更新只需要O(1)代价 fi+1(aj),gi+1(aj)的更新只需要O(1)代价

进而 a r r [ 0 : i + 1 ] 的 h i + 1 序列重建,只需要 O ( n ) 的代价 进而{arr[0:i+1]的h_{i+1}序列重建,只需要O(n)的代价} 进而arr[0:i+1]hi+1序列重建,只需要O(n)的代价

a r r [ 0 : i + 1 ] 的最小逆序也可以 O ( n ) 求解 arr[0:i+1]的最小逆序也可以O(n)求解 arr[0:i+1]的最小逆序也可以O(n)求解

这样n长度的数组,只需要 O ( n 2 ) O(n^2) O(n2)求解得最终的解


如果这题,改为在线查询,可能会更难


n = int(input())
arr = list(map(int, input().split()))

f = [0] * n
g = [0] * n

acc = 0
res = []
for i in range(n):
    for j in range(i - 1, -1, -1):
        if arr[j] < arr[i]:
            f[j] += 1
            g[i] += 1
        elif arr[j] > arr[i]:
            g[j] += 1
            f[i] += 1
    acc += f[i]
    ans = acc
    tmp = 0
    for j in range(i):
        tmp = tmp + f[j] - g[j]
        ans = min(ans, acc + tmp)
    res.append(ans)

print (*res)

写在最后

alt

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue之一键部署的shell脚本和它的点.bat文件、海螺AI、ChatGPT

MENU 前言vite.config.ts的配置deploy文件夹的其他内容remote.shpwd.txtdeploy.bat 前言 1、在src同级新建deploy.bat文件&#xff1b; 2、在src同级新建deploy文件夹&#xff0c;文件夹中新建pwd.txt和remote.sh文件&#xff1b; 3、配置好后&#xff0c;直接双击deploy.bat文…

Java_FileIO流

存储数据的方案 有些数据想长久保存起来&#xff0c;咋整&#xff1f; 文件时非常重要的存储方式&#xff0c;在计算机硬盘中。 即便断电&#xff0c;或者程序终止了&#xff0c;存储在硬盘文件中的数据也不会丢失。 File File 是Java.io.包下的类&#xff0c;File类对象&…

C++ string字符串的使用和简单模拟实现

目录 前言 1. string简介 2. string的使用和简单模拟实现 2.1 string类的定义 2.2 string(),~string()和c_str() 2.2 size&#xff0c;重载符号[ ]&#xff0c;begin和end函数 2.3 push_back&#xff0c;reserve&#xff0c;append&#xff0c;运算符重载 2.4 insert和…

DDPM公式推导(三)

2 Background 扩散模型【53】是一种以 p θ ( x 0 ) : ∫ p θ ( x 0 : T ) d x 1 : T p_\theta\left(\mathbf{x}_0\right):\int p_\theta\left(\mathbf{x}_{0: T}\right) d \mathbf{x}_{1: T} pθ​(x0​):∫pθ​(x0:T​)dx1:T​ 形式的潜在变量模型&#xff0c;其中 x 1…

机器真的能思考、学习和智能地行动吗?

In this post, were going to define what machine learning is and how computers think and learn. Were also going to look at some history relevant to the development of the intelligent machine. 在这篇文章中&#xff0c;我们将定义机器学习是什么&#xff0c;以及…

BerkeleyDB练习

代码; #include <db.h> #include <stdio.h>int main() {DB *dbp;db_create(&dbp, NULL, 0);printf("Berkeley DB version: %s\n", db_version(NULL, NULL, NULL));dbp->close(dbp, 0);return 0; } 编译运行

Android studio在Ubuntu桌面上 创建桌面图标,以及导航栏图标

Android studio在Ubuntu桌面上 创建桌面图标&#xff0c;以及导航栏图标 1. 下载Android studio for Lunux 免安装版本之后&#xff0c;解压 2. 通过控制台运行 ~/Documents/android-studio-2024.1.1.2-linux/android-studio/bin$ ./studio.sh 3. 选择菜单&#xff0c;Tools…

1586. 扫地机器人

问题描述 Mike同学在为扫地机器人设计一个在矩形区域中行走的算法,Mike是这样设计的:先把机器人放在出发点 (1,1)(1,1) 点上,机器人在每个点上都会沿用如下的规则来判断下一个该去的点是哪里。规则:优先向右,如果向右不能走(比如:右侧出了矩形或者右侧扫过了)则尝试向…

基于51单片机的烟雾报警器设计-ADC0809

一.硬件方案 火灾报警器采用51单片机为核心控制器&#xff0c;利用气体传感器MQ-2、ADC0809模数转换器、DS18B20温度传感器等实现基本功能。通过这些传感器和芯片&#xff0c;当环境中可燃气体浓度或温度等发生变化时系统会发出相应的灯光报警信号和声音报警信号&#xff0c;以…

28.启动与暂停程序

上一个内容&#xff1a;27.设计注入功能界面 以它 27.设计注入功能界面 的代码为基础进行修改 点击添加游戏按钮之后就把游戏启动了 CWndINJ.cpp文件中修改&#xff1a; void CWndINJ::OnBnClickedButton1() {// TODO: 在此添加控件通知处理程序代码/*ExeLst.InsertItem(0, L…

Vue I18n国际化插件

Vue I18n国际化插件 安装目录结构及文件内容./locales/lang/zh.js./locales/lang/en.js./locales/index.js main.js引入页面具体使用及语言切换&#xff08;Vue3&#xff09;刷新保存原语言&#xff0c;App.vue添加路由守卫注意点 中文文档&#xff1a; https://kazupon.githu…

69. UE5 RPG 使用Gameplay Cue 实现技能表现效果

在上一章中&#xff0c;我们实现了敌人的攻击技能的特效和音效。如果我们在多人模式下打开&#xff0c;发现&#xff0c;其它客户端看不到对应的效果。 造成这种问题的原因是因为敌人的技能是运行在服务器端的&#xff0c;它只复制到拥有它的客户端&#xff0c;而敌人的效果对于…

英伟达与斯坦福携手,打造未来全息XR眼镜:头带时代的终结

在XR(扩展现实)技术的演进过程中,一个显著的挑战在于如何平衡设备的便携性与视觉体验。传统的XR设备由于需要厚重的头带固定光学器件和显示器,不仅增加了体积,还为用户带来了社交上的不便。然而,随着英伟达与斯坦福大学戈登韦茨斯坦教授领导的研究团队的合作,这一难题似…

meilisearch的分页

Elasticsearch 做为老牌搜索引擎&#xff0c;功能基本满足&#xff0c;但复杂&#xff0c;重量级&#xff0c;适合大数据量。 MeiliSearch 设计目标针对数据在 500GB 左右的搜索需求&#xff0c;极快&#xff0c;单文件&#xff0c;超轻量。 所以&#xff0c;对于中小型项目来说…

探地雷达正演模拟,基于时域有限差分方法,四

突然发现第三章后半部分已经讲了使用接收记录成像的问题&#xff0c;所以这一章只讲解简单的数据分析。 &#xff08;均以宽角法数据为例子&#xff0c;剖面法数据处理方式都是相同的&#xff09;假设&#xff0c;我们现在已经获得了一个GPR记录&#xff0c;可以是常用的.sgy格…

DAY03 HTML

文章目录 一 表格1. 表格的语法2. 表格的可选标记3. 不规则的单元格&#xff08;合并单元格&#xff09;4. 表格的属性5. 表格的大小 二 列表1. 有序列表2. 无序列表3. 属性4. 列表的嵌套5. 定义列表【了解】 三 表单(重点)1. 表单的语法2. 表单的控件分类3. input元素4. selec…

为什么说Python 是胶水语言?

​ "Python 是胶水语言"这一说法是指它很擅长将不同的程序或代码库连接在一起&#xff0c;能够让来自不同编程语言或框架的组件无缝协作。Python 具有丰富的库和简单的语法&#xff0c;使得它可以轻松调用其他语言编写的程序或使用不同技术栈的模块。 ​ 以下是几个…

如何区分人工智能生成的图像与真实照片(下)

4 功能上的不合理性 AI 生成的图像往往会因为缺乏对现实世界物体结构和相互作用的了解&#xff0c;而产生各种功能不合理之处。这些不合理之处主要表现在以下几个方面&#xff1a; 4.1 构图不合理 物体关系不合逻辑: AI 生成的图像中&#xff0c;物体和人物之间的关系可能不符…

哈希表、递归在二叉树中的应用-1372. 二叉树中的最长交错路径

题目链接及描述 1372. 二叉树中的最长交错路径 - 力扣&#xff08;LeetCode&#xff09; 题目分析 题目所述&#xff0c;计算在二叉树中交替遍历的最大深度【左->右->左】【右->左->右】&#xff0c;例如对于从当前根节点root出发&#xff0c;则此时遍历方向有两个…

持续集成jenkins+gitee

首先要完成gitee部署&#xff0c;详见自动化测试git的使用-CSDN博客 接下来讲如何从git上自动拉取代码&#xff0c;实现jenkins无人值守&#xff0c;定时执行测试&#xff0c;生成测试报告。 需要这三个安装包 由于目前的jenkins需要至少java11到java17的版本&#xff0c;所以…