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

news2024/9/29 15:27:50

前言

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

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

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

相关文章

Windows上构建一个和Linux类似的Terminal

preview 目的是在Windows上构建一个和Linux类似的Terminal&#xff0c;让Windows炼丹和Linux一样舒适&#xff0c;同是让Terminal取代Xshell完成远程链接。 预览如下图 在Linux下我们使用zsh和oh-my-zsh结合&#xff0c;Windows下我们使用powershell7和oh-my-posh结合。 前提…

力扣● 1049. 最后一块石头的重量 II ● 494. 目标和 ● 474.一和零

● 1049. 最后一块石头的重量 II 题目要把石头分成两堆&#xff0c;这两堆的重量差值最小。相撞之后剩下的石头重量就最小。其实就是要尽量把石头分为差不多重量的两堆&#xff0c;和昨天的● 416. 分割等和子集相似&#xff0c;这样就转换成了01背包问题。 和416题一样&…

【字符串相加】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 字符串相加 方法一&#xff1a; 方法二&#xff1a; 总结 前言 世上有两种耀眼的光芒&#xff0c;一种是正在升起的太阳&#xff0c;一种是正在努力学习编程的…

腾讯云幻兽帕鲁游戏存档迁移教程,本地单人房迁移/四人世界怎么迁移存档?

腾讯云幻兽帕鲁游戏存档迁移的方法主要包括以下几个步骤&#xff1a; 登录轻量云控制台&#xff1a;首先&#xff0c;需要登录到轻量云控制台&#xff0c;这是进行存档迁移的前提条件。在轻量云控制台中&#xff0c;可以找到接收存档的服务器卡片&#xff0c;并点击进入实例详情…

LeetCode 2368.受限条件下可到达节点的数目:搜索 + 哈希表

【LetMeFly】2368.受限条件下可到达节点的数目&#xff1a;搜索 哈希表 力扣题目链接&#xff1a;https://leetcode.cn/problems/reachable-nodes-with-restrictions/ 现有一棵由 n 个节点组成的无向树&#xff0c;节点编号从 0 到 n - 1 &#xff0c;共有 n - 1 条边。 给…

ecmascript 6+(2)

引用数据类型&#xff1a; Object, Array, RegExp, Date等 包装类型&#xff1a;&#xff08;底层数据类型会将简单数据类型包装为对象&#xff09; String, Number, Boolean等&#xff08;都是基本数据类型的构造函数&#xff09; Object Object.keys(对象) 返回数组&…

ctf_show笔记篇(web入门---php特性)

目录 php特性 89&#xff1a;直接数组绕过preg_match当遇到数组时会直接报错输出0 90&#xff1a;这里利用了intval的特性 91&#xff1a;这里需要细节一点 92-93&#xff1a;这两题的方法很多可以发散思维 94&#xff1a;还是利用小数绕过例如4476.0 95&#xff1a;这里…

spring boot 修复 Spring Framework URL解析不当漏洞(CVE-2024-22243)

漏洞描述 当应用程序使用UriComponentsBuilder来解析外部提供的URL&#xff08;如通过查询参数&#xff09;并对解析的URL的主机执行验证检查时可能容易受到Open重定向攻击和SSRF攻击&#xff0c;导致网络钓鱼和内部网络探测等。 受影响产品或系统 6.1.0 < Spring Framew…

【bioinformation 2】生物数据库

&#x1f31e;欢迎来到AI医学的世界 &#x1f308;博客主页&#xff1a;卿云阁 &#x1f48c;欢迎关注&#x1f389;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f31f;本文由卿云阁原创&#xff01; &#x1f4c6;首发时间&#xff1a;&#x1f339;2024年3月3日&…

【新书推荐】11.1 子程序设计

第十一章 子程序及参数传递 本章先讲述子程序设计的方法&#xff0c;然后介绍在子程序调用中参数的四种传递方法。 11.1 子程序设计 在前面的示例和练习中&#xff0c;会发现程序中会有一些反复使用到的代码片段。我们将程序中反复出现的程序片段设计成子程序&#xff0c;这样…

DM数据库学习之路(十九)DM8数据库sysbench部署及压力测试

sysbench部署 安装依赖 yum -y install make automake libtool pkgconfig libaio-devel vim-common 上传sysbench源代码 sysbench_tool.tar 测试是否安装成功 $ /opt/sysbench/sysbench-master-dpi/src/lua $ ./sysbench --version sysbench 1.1.0 sysbench测试DM 测试…

【STK】手把手教你利用STK进行仿真-STK软件基础02 STK系统的软件界面01 STK的界面窗口组成

STK系统是Windows窗口类型的桌面应用软件,功能非常强大。在一个桌面应用软件中集成了仿真对象管理、仿真对象属性参数、设置、空间场景二三维可视化、场景显示控制欲操作、仿真结果报表定制与分析、对象数据管理、仿真过程控制、外部接口连接和系统集成编程等复杂的功能。 STK…

MyBatis源码分析之基础支持层解析器

(/≧▽≦)/~┴┴ 嗨~我叫小奥 ✨✨✨ &#x1f440;&#x1f440;&#x1f440; 个人博客&#xff1a;小奥的博客 &#x1f44d;&#x1f44d;&#x1f44d;&#xff1a;个人CSDN ⭐️⭐️⭐️&#xff1a;传送门 &#x1f379; 本人24应届生一枚&#xff0c;技术和水平有限&am…

录制用户操作实现自动化任务

先上视频&#xff01;&#xff01; 流程自动化工具-录制操作绘制流程 这个想法之前就有了&#xff0c;趁着周末时间给它撸出来。 实现思路 从之前的文章自动化桌面未来展望中已经验证了录制绘制流程图的可行性。基于DOM录制页面操作轨迹的思路监听页面点击、输入事件即可&…

蓝桥杯练习题——二分

1.借教室 思路 1.随着订单的增加&#xff0c;每天可用的教室越来越少&#xff0c;二分查找最后一个教室没有出现负数的订单编号 2.每个订单的操作是 [s, t] 全部减去 d #include<iostream> #include<cstring> using namespace std; const int N 1e6 10; int d[…

Linux之相对路径、绝对路径、特殊路径符

相对路径和绝对路径 cd /root/temp 绝对路径写法 cd temp 相对路径写法 1、绝对路径&#xff1a;以根目录为起点&#xff0c;描述路径的一种写法&#xff0c;路径描述以 / 开头。 2、相对路径&#xff1a;以当前目录为起点&#xff0c;路径描述无需以 / 开头。 特殊路径符 如…

cRIO9040中NI9871模块的测试

硬件准备 CompactRIO9040NI9871直流电源&#xff08;可调&#xff09;网线RJ50转DB9线鸣志STF03-R驱动器和步进电机 软件安装 参考&#xff1a;cRIO9040中NI9381模块的测试 此外&#xff0c;需安装NI-Serial 9870和9871扫描引擎支持 打开NI Measurement&#xff06;Automa…

C++之set、multiset

1、set简介 set是一种关联式容器&#xff0c;包含的key值唯一&#xff0c;所有元素都会在插入时自动被排序&#xff0c;其存储结构为红黑树。set只能通过迭代器(iterator)访问。 set和multiset的区别&#xff1a; &#xff08;1&#xff09;set不允许容器中有重复的元素&…

C++_程序流程结构_选择结构_if

程序流程结构 C/C支持最基本的三种程序运行结构&#xff1a;顺序、选择、循环结构 顺序结构&#xff1a;程序按顺序执行&#xff0c;不发生跳转选择结构&#xff1a;依据条件是否满足&#xff0c;有选择地执行相应功能循环结构&#xff1a;依据条件是否满足&#xff0c;循环多…

跟 AI 学 StarRocks:简介

因为要支持公司的 BI 建设&#xff0c;团队引入了 StarRocks 数据库&#xff0c;此前我没有了解过此项技术&#xff0c;不过因为有架构师引入了此项技术栈&#xff0c;就顺便学习一下。 一、什么是 MPP 数据库&#xff1f; MPP 数据库指的是大规模并行处理&#xff08;Massiv…