力扣 第 125 场双周赛 解题报告 | 珂学家 | 树形DP + 组合数学


前言

image.png


整体评价

T4感觉有简单的方法,无奈树形DP一条路上走到黑了,这场还是有难度的。


T1. 超过阈值的最少操作数 I

思路: 模拟

class Solution {
    public int minOperations(int[] nums, int k) {
        return (int)Arrays.stream(nums).filter(x -> x < k).count();
    }
}

T2. 超过阈值的最少操作数 II

思路: 模拟

按题意模拟即可,需要注意int溢出问题就行。

class Solution {
    public int minOperations(int[] nums, int k) {
        PriorityQueue<Long> pq = new PriorityQueue<>();
        for (long num : nums) {
            pq.offer(num);
        }
        int ans = 0;
        while (pq.peek() < k) {
            long x = pq.poll(), y = pq.poll();
            pq.offer(Math.min(x, y) * 2 + Math.max(x, y));
            ans++;
        }
        return ans;
    }
}

T3. 在带权树网络中统计可连接服务器对数目

思路: 枚举 + dfs/bfs + 组合数学

因为树的点数n( n ≤ 1000 n\le1000 n1000), 所以枚举点,从该点进行dfs/bfs,然后对每个分支进行组合统计。

组合统计的核心

点 u 出发的各个分支满足整除的数,组合序列为 c 0 , c 1 , c 2 , c 3 , . . . , c m 点u出发的各个分支满足整除的数,组合序列为 c_0, c_1, c_2, c_3, ..., c_m u出发的各个分支满足整除的数,组合序列为c0,c1,c2,c3,...,cm

其 s = ∑ i = 0 i = m c i 其 s = \sum_{i=0}^{i=m} c_i s=i=0i=mci

结果为 r e s [ u ] = ( ∑ i = 0 i = m c i ∗ ( s − c i ) ) / 2 结果为 res[u] = (\sum_{i=0}^{i=m} c_i * (s - c_i)) / 2 结果为res[u]=(i=0i=mci(sci))/2

这样时间复杂度为 O ( n 2 ) O(n^2) O(n2), 是可以接受的。

class Solution {

    List<int[]> []g;
    int signalSpeed;
    
    // fa是阻断点
    int bfs(int u, int w, int fa) {
        int res = 0;
        boolean[] vis = new boolean[g.length];
        Deque<int[]> deq = new ArrayDeque<>();
        vis[u] = true;
        deq.offer(new int[] {u, w});
        if (w % signalSpeed == 0) {
            res ++;
        }
        while (!deq.isEmpty()) {
            int[] cur = deq.poll();
            int p = cur[0];
            int v = cur[1];
            for (int[] e: g[p]) {
                if (e[0] == fa) continue;
                if (vis[e[0]]) continue;
                if ((v + e[1]) % signalSpeed == 0) res++;
                deq.offer(new int[] {e[0], v + e[1]});
                vis[e[0]] = true;
             }
        }
        return res;
    }

    public int[] countPairsOfConnectableServers(int[][] edges, int signalSpeed) {
        int n = edges.length + 1;

        g = new List[n];
        Arrays.setAll(g, x->new ArrayList<>());
        this.signalSpeed = signalSpeed;
        
        for (int[] e: edges) {
            g[e[0]].add(new int[] {e[1], e[2]});
            g[e[1]].add(new int[] {e[0], e[2]});
        }

        int[] res = new int[n];
        for (int i = 0; i < n; i++) {
            int sum = 0;
            
            List<Integer> lists = new ArrayList<>();
            for (int[] e: g[i]) {
                int tmp = bfs(e[0], e[1], i);
                lists.add(tmp);
                sum += tmp;
            }

            int tot = 0;
            for (int j = 0; j < lists.size(); j++) {
                tot += lists.get(j) * (sum - lists.get(j));
            }
            res[i] = tot / 2;
        }
        return res;
    }

}

如果该题把n变成 n ≤ 1 0 5 n\le10^5 n105, 那该如何解呢?

感觉换根 D P 可行,但是需要限制 s i g n a l S p e e d 范围在 100 之内 , 这样可控制在 O ( 1 0 7 ) 感觉换根DP可行,但是需要限制 signalSpeed 范围在100之内, 这样可控制在O(10^7) 感觉换根DP可行,但是需要限制signalSpeed范围在100之内,这样可控制在O(107)

如果signalSpeed很大,感觉没辙啊。


T4. 最大节点价值之和

思路: 树形DP

树形DP的解法更加具有通用性,所以比赛就沿着这个思路写。

如果操作不是异或,那这个思路就更有意义 如果操作不是异或,那这个思路就更有意义 如果操作不是异或,那这个思路就更有意义

对于任意点u, 其具备两个状态。

d p [ u ] [ 0 ] , d p [ u ] [ 1 ] , 表示参与和没有参与异或下的以 u 为根节点的子树最大和。 dp[u][0], dp[u][1], 表示参与和没有参与异或下的以u为根节点的子树最大和。 dp[u][0],dp[u][1],表示参与和没有参与异或下的以u为根节点的子树最大和。

那么其转移方程,其体现在当前节点u和其子节点集合S( v ∈ u 的子节点 v\in u的子节点 vu的子节点)的迭代递推转移。

class Solution {

    int k;
    int[] nums;
    List<Integer>[]g;

    long[][] dp;

    void dfs(int u, int fa) {
        // 该节点没参与, 该节点参与了
        long r0 = nums[u], r1 = Long.MIN_VALUE / 10;

        for (int v: g[u]) {
            if (v == fa) continue;
            dfs(v, u);

            long uRev0 = r0 + (nums[u]^k) - nums[u];
            long uRev1 = r1 - (nums[u]^k) + nums[u];
            long vRev0 = dp[v][0] + (nums[v]^k) - nums[v];
            long vRev1 = dp[v][1] - (nums[v]^k) + nums[v];

            long x0 = Math.max(
                    r0 + Math.max(dp[v][0], dp[v][1]),
                    Math.max(uRev1 + vRev1, uRev1 + vRev0)
            );

            long x1 = Math.max(
                    r1 + Math.max(dp[v][1], dp[v][0]),
                    Math.max(uRev0 + vRev0, uRev0 + vRev1)
            );

            r0 = x0;
            r1 = x1;
        }

        dp[u][0] = r0;
        dp[u][1] = r1;
    }

    public long maximumValueSum(int[] nums, int k, int[][] edges) {
        int n = nums.length;

        this.g = new List[n];
        this.nums = nums;
        this.k = k;

        this.dp = new long[n][2];
        Arrays.setAll(g, x -> new ArrayList<>());

        for (int[] e: edges) {
            g[e[0]].add(e[1]);
            g[e[1]].add(e[0]);
        }

        dfs(0, -1);
        return Math.max(dp[0][0], dp[0][1]);
    }
}
class Solution:
    def maximumValueSum(self, nums: List[int], k: int, edges: List[List[int]]) -> int:
        n = len(nums)
        g = [[] for _ in range(n)]
        for e in edges:
            g[e[0]].append(e[1])
            g[e[1]].append(e[0])
        
        dp = [[0] * 2 for _ in range(n)]
        
        def dfs(u, fa):
            r0, r1 = nums[u], -0x3f3f3f3f3f
            
            for v in g[u]:
                if v == fa:
                    continue
                dfs(v, u)
                
                uRev0 = r0 + (nums[u]^k) - nums[u];
                uRev1 = r1 - (nums[u]^k) + nums[u];
                vRev0 = dp[v][0] + (nums[v]^k) - nums[v];
                vRev1 = dp[v][1] - (nums[v]^k) + nums[v];
                
                t0 = max(r0 + max(dp[v][0], dp[v][1]), max(uRev1 + vRev0, uRev1 + vRev1))
                t1 = max(r1 + max(dp[v][0], dp[v][1]), max(uRev0 + vRev0, uRev0 + vRev1))
                
                r0, r1 = t0, t1
            
            dp[u][0], dp[u][1] = r0, r1
        
        dfs(0, -1)
        
        return max(dp[0][0], dp[0][1])

由于异或的特点,所以这题可以抛弃边的束缚。

任意两点 u , v ,可以简单构造一条路径,只有端点 ( u , v ) 出现 1 次,其他点都出现 2 次 任意两点u,v,可以简单构造一条路径,只有端点(u,v)出现1次,其他点都出现2次 任意两点u,v,可以简单构造一条路径,只有端点(u,v)出现1次,其他点都出现2

异或涉及边的两点,因此异或的点必然是偶数个,这是唯一的限制.

class Solution {
    public long maximumValueSum(int[] nums, int k, int[][] edges) {
        long sum = 0;
        PriorityQueue<Long> pq = new PriorityQueue<>(Comparator.comparing(x -> -x));
        for (int v: nums) {
            pq.offer((long)(v ^ k) - v);
            sum += v;
        }
        
        while (pq.size() >= 2) {
            long t1 = pq.poll();
            long t2 = pq.poll();
            if (t1 + t2 > 0) {
                sum += t1 + t2;
            } else {
                break;
            }
        }
        
        return sum;
    }
}
class Solution:
    def maximumValueSum(self, nums: List[int], k: int, edges: List[List[int]]) -> int:
        s = sum(nums)
        arr = [(v ^ k) - v for v in nums]
        arr.sort(key=lambda x: -x)
        
        n = len(nums)
        for i in range(0, n, 2):
            if i + 1 < n and arr[i] + arr[i + 1] > 0:
                s += arr[i] + arr[i + 1]
        return s

写在最后

image.png

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

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

相关文章

Premiere Pro:视频制作的瑞士军刀,让创意飞翔!

Premiere Pro&#xff0c;由Adobe公司推出的专业非线性视频编辑软件&#xff0c;已成为众多视频制作人员的首选工具。其功能之强大、操作之便捷&#xff0c;为视频制作带来了革命性的改变。 首先&#xff0c;Premiere Pro支持多种视频格式的导入和编辑&#xff0c;从剪辑、修剪…

【微服务】在Java体系中SpringCloud和SpringCloud Alibaba各通过哪些具体组件来实现微服务架构呢?

前面我们介绍了微服务架构的各个组件以及各组件的职责&#xff0c;在Java领域中&#xff0c;Spring可以说是无人不知无人不晓的&#xff0c;我们现代的企业级应用和互联网应用&#xff0c;很大一部分都是构建在Spring生态体系上的&#xff0c;同样&#xff0c;实现微服务架构的…

Redis常用指令,jedis与持久化

1.redis常用指令 第一个是key的常用指令&#xff0c;第二个是数据库的常用指令 前面的那些指令都是针对某一个数据类型操作的&#xff0c;现在的都是对所有的操作的 1.key常用指令 key应该设计哪些操作 key是一个字符串&#xff0c;通过key获取redis中保存的数据 对于key…

GCN原理回顾论文导读

Cora_dataset description Cora数据集是一个常用的学术文献用网络数据集&#xff0c;用于研究学术文献分类和图网络分析等任务。 该数据集由机器学习领域的博士论文摘要组成&#xff0c;共计2708篇论文&#xff0c;涵盖了7个不同的学科领域。每篇论文都有一个唯一的ID&#xf…

c++之旅——第四弹

大家好啊&#xff0c;这里是c之旅第三弹&#xff0c;跟随我的步伐来开始这一篇的学习吧&#xff01; 如果有知识性错误&#xff0c;欢迎各位指正&#xff01;&#xff01;一起加油&#xff01;&#xff01; 创作不易&#xff0c;希望大家多多支持哦&#xff01; 本篇文章的主…

【css面试题】BFC

参考文章1 参考文章2 什么是BFC BFC全称是Block Formatting Context&#xff0c;意思就是块级格式化上下文。你可以把BFC看做一个容器&#xff0c;容器里边的元素不会影响到容器外部的元素。 BFC的特性 BFC是一个块级元素&#xff0c;块级元素在垂直方向上依次排列。 BFC是…

QT 网络编程 8

1 基础知识 udp tcp 2 UDP 框架 客户端: QUdpSocket x; qint64 writeDatagram( const char *data, qint64 size, const QHostAddress &address, quint16 port );服务器: void Server::initSocket(){udpSocket new QUdpSocket(this);udpSocket->bind(QHostAddress…

【Redis | 第七篇】Redis过期策略、内存淘汰策略

文章目录 7.Redis过期策略、内存淘汰策略7.1过期策略7.2内存淘汰策略 7.Redis过期策略、内存淘汰策略 7.1过期策略 我们在set key的时候&#xff0c;可以给它设置一个过期时间&#xff0c;比如expire key 60。指定这key60s后过期。 60s后&#xff0c;redis是如何处理的嘛&am…

性别和年龄的视频实时监测项目

注意&#xff1a;本文引用自专业人工智能社区Venus AI 更多AI知识请参考原站 &#xff08;[www.aideeplearning.cn]&#xff09; 性别和年龄检测 Python 项目 首先介绍性别和年龄检测的高级Python项目中使用的专业术语 什么是计算机视觉&#xff1f; 计算机视觉是使计算机能…

ER-NeRF实时对话数字人模型训练与部署

ER-NeRF是基于NeRF用于生成数字人的方法&#xff0c;可以达到实时生成的效果。 下载源码 cd D:\Projects\ git clone https://github.com/Fictionarry/ER-NeRF cd D:\Projects\ER-NeRF 下载模型 准备面部解析模型 wget https://github.com/YudongGuo/AD-NeRF/blob/master/…

如何预估系统的瓶颈

如何预估系统的瓶颈 1 CPU1.1 CPU和同吞吐量 2 内存3 磁盘IO4 网络宽带5 数据库服务器6 APP服务端 CPU 使用率、内存占用、网络流量、磁盘 IO等指标&#xff0c;异常或者持续高位的情况下&#xff0c;都可能是系统瓶颈的表现。 1 CPU CPU使用率正常在70%左右&#xff0c;如果…

力扣hot100:42.接雨水

一、从单个水柱本身考虑 下标为i的水柱能接的雨水&#xff0c;取决于它左边最高的水柱 和 右边最高的水柱的最小值&#xff08;包括它本身&#xff09;。 为了理解这一性质&#xff0c;我们可以这样想象&#xff1a;取出左边最高和最边最高的水柱&#xff0c;将其比作一个碗的边…

绘制一下包络线

clear clc close all % 生成衰减信号 % 生成衰减曲线带有随机信号 fs 50; % 采样率 t 0:1/fs:100; % 时间向量&#xff0c;总时长为5秒 frequency0.5; signal exp(-0.05* t).*sin(2*pi*frequency*t); % 衰减曲线带有随机信号 % 计算包络线 [upper_envelope, lower_…

基于springboot+vue的教师工作量管理系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

ImageGlass:重塑你的图片查看体验,探索视觉艺术

名人说&#xff1a;莫道桑榆晚&#xff0c;为霞尚满天。——刘禹锡&#xff08;刘梦得&#xff0c;诗豪&#xff09; 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 一、什么是ImageGlass&#xff1f;①ImageGlass…

Python 编辑工具 Jupyter notebook

Jupyter notebook Jupyter Notebook是基于网页的用于交互计算的应用程序。其可被应用于全过程计算&#xff1a;开发、文档编写、运行代码和展示结果。——Jupyter Notebook官方介绍 官网&#xff1a;Project Jupyter | Home Jupyter Notebook 是一个开源的交互式计算环境&#…

数据结构——lesson5栈和队列详解

hellohello~这里是土土数据结构学习笔记&#x1f973;&#x1f973; &#x1f4a5;个人主页&#xff1a;大耳朵土土垚的博客 &#x1f4a5; 所属专栏&#xff1a;数据结构学习笔记 &#x1f4a5;对于顺序表链表有疑问的都可以在上面数据结构的专栏进行学习哦~感谢大家的观看与…

Java电梯模拟

Java电梯模拟 文章目录 Java电梯模拟前言一、UML类图二、代码三、测试 前言 此程序为单线程简单模拟电梯(初版)&#xff0c;如果存在问题或者设计不合理的地方&#xff0c;请大家帮忙指出。 一、UML类图 二、代码 电梯调度器 package cn.xx.evevator;import java.util.*;pub…

【间说八股】面试官:我看你这里用到了模板模式?你能不能说一下什么是模板模式

模板模式 行为模式&#xff1a;这类模式负责对象间的高效沟通和职责委派。 模板方法模式是一种行为设计模式&#xff0c; 它在超类中定义了一个算法的框架&#xff0c; 允许子类在不修改结构的情况下重写算法的特定步骤。 模板方法模式是一种行为设计模式&#xff0c;其核心思想…

下载github项目到pycharm

一、下载git 1.下载git链接 https://git-scm.com/ 2.一路点击next&#xff0c;最后finish 二、使用git 1.安装成功后在开始菜单栏会找到如下内容&#xff0c;其中常用的是Git Bash 2.点击Git Bash 3.这里就可以克隆github上的代码了 点击复制&#xff0c;在命令行输入…