草庐IT

【2022年蓝桥杯真题之带权并查集问题】推导部分和

未见花闻 2023-04-14 原文

⭐️前面的话⭐️

【2022年蓝桥杯真题之带权并查集问题】推导部分和
对于一个长度为 N N N 的整数数列 A 1 , A 2 , ⋯ A N A_1, A_2, \cdots A_N A1,A2,AN, 小蓝想知道下标 l l l r r r 的部分和 ∑ i = l r = A l + A l + 1 + ⋯ + A r \sum_{i=l}^r=A_l+A_{l+1}+\cdots+A_r i=lr=Al+Al+1++Ar 是多少?
然而, 小蓝并不知道数列中每个数的值是多少, 他只知道它的 M M M 个部 分和的值。其中第 i i i 个部分和是下标 l i l_i li r i r_i ri 的部分和 ∑ j = l i r i = \sum_{j=l_i}^{r_i}= j=liri= A l i + A l i + 1 + ⋯ + A r i A_{l i}+A_{l i+1}+\cdots+A_{r i} Ali+Ali+1++Ari, 值是 S i S_i Si 。解题代码:Java, C++。

📒博客主页:未见花闻的博客主页
🎉欢迎关注🔎点赞👍收藏⭐️留言📝
📌本文由未见花闻原创,CSDN首发!
📆首发时间:🌴2023年3月20日🌴
✉️坚持和努力一定能换来诗与远方!
💭推荐书籍:📚《算法》,📚《算法导论》
💬参考在线编程网站:🌐牛客网🌐力扣
博主的码云gitee,平常博主写的程序代码都在里面。
博主的github,平常博主写的程序代码都在里面。
🍭作者水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢!


📌导航小助手📌


⭐️推导部分和⭐️

🔐题目详情

问题描述

对于一个长度为 N N N 的整数数列 A 1 , A 2 , ⋯ A N A_1, A_2, \cdots A_N A1,A2,AN, 小蓝想知道下标 l l l r r r 的部分和 ∑ i = l r = A l + A l + 1 + ⋯ + A r \sum_{i=l}^r=A_l+A_{l+1}+\cdots+A_r i=lr=Al+Al+1++Ar 是多少?
然而, 小蓝并不知道数列中每个数的值是多少, 他只知道它的 M M M 个部 分和的值。其中第 i i i 个部分和是下标 l i l_i li r i r_i ri 的部分和 ∑ j = l i r i = \sum_{j=l_i}^{r_i}= j=liri= A l i + A l i + 1 + ⋯ + A r i A_{l i}+A_{l i+1}+\cdots+A_{r i} Ali+Ali+1++Ari, 值是 S i S_i Si

输入格式

第一行包含 3 个整数 N 、 M N 、 M NM Q Q Q 。分别代表数组长度、已知的部 分和数量和询问的部分和数量。
接下来 M M M 行, 每行包含 3 个整数 l i , r i , S i l_i, r_i, S_i li,ri,Si
接下来 Q Q Q 行, 每行包含 2 个整数 l l l r r r, 代表一个小蓝想知道的部分 和。

输出格式

对于每个询问, 输出一行包含一个整数表示答案。如果答案无法确定, 输出 UNKNOWN。

样例输入

5 3 3
1 5 15
4 5 9
2 3 5
1 5
1 3
1 2

样例输出

15
6
UNKNOWN

评测用例规模与约定

对于 10 % 10 \% 10% 的评测用例, 1 ≤ N , M , Q ≤ 10 , − 100 ≤ S i ≤ 100 1 \leq N, M, Q \leq 10,-100 \leq S_i \leq 100 1N,M,Q10,100Si100
对于 20 % 20 \% 20% 的评测用例, 1 ≤ N , M , Q ≤ 20 , − 1000 ≤ S i ≤ 1000 1 \leq N, M, Q \leq 20,-1000 \leq S_i \leq 1000 1N,M,Q20,1000Si1000
对于 30 % 30 \% 30% 的评测用例, 1 ≤ N , M , Q ≤ 50 , − 10000 ≤ S i ≤ 1 \leq N, M, Q \leq 50,-10000 \leq S_i \leq 1N,M,Q50,10000Si 10000 。
对于 40 % 40 \% 40% 的评测用例, 1 ≤ N , M , Q ≤ 1000 , − 1 0 6 ≤ S i ≤ 1 0 6 1 \leq N, M, Q \leq 1000,-10^6 \leq S_i \leq 10^6 1N,M,Q1000,106Si106
对于 60 % 60 \% 60% 的评测用例, 1 ≤ N , M , Q ≤ 10000 , − 1 0 9 ≤ S i ≤ 1 \leq N, M, Q \leq 10000,-10^9 \leq S_i \leq 1N,M,Q10000,109Si 1 0 9 10^9 109
对于所有评测用例, 1 ≤ N , M , Q ≤ 1 0 5 , − 1 0 12 ≤ S i ≤ 1 \leq N, M, Q \leq 10^5,-10^{12} \leq S_i \leq 1N,M,Q105,1012Si 1 0 12 , 1 ≤ l i ≤ r i ≤ N , 1 ≤ l ≤ r ≤ N 10^{12}, 1 \leq l_i \leq r_i \leq N, 1 \leq l \leq r \leq N 1012,1liriN,1lrN 。数据保证没有矛盾。

运行限制

  • 最大运行时间:3s
  • 最大运行内存: 512M

💡解题思路

根据前缀和的经验,我们知道区间 [ l , r ] [l, r] [l,r]的和可以表示为 d [ r ] − d [ l − 1 ] d[r] - d[l - 1] d[r]d[l1],其中 d d d为前缀和数组,这道题差不多是反着过来的,题目会给定若干组区间和,然后需要根据这些信息去推导其他区间的区间和,第一眼看了是完全懵逼的,看了一位大佬的题解后【大佬贴贴】,明白可以使用带权并查集来做,这个和y总讲的算法基础课中的【食物链】这道题有点像。

前缀和是第一个元素为参照,陆续求出后续元素的累加和,利用区间相减的原则推导出某段区间的和。使用带权并查集来做可以类比一下,我们以并查集的根节点为参照,如 d [ r ] d[r] d[r]就表示 r r r结点到所在并查集的距离,同理对于 [ l , r ] [l, r] [l,r]的区间和也可以使用 d [ r ] − d [ l − 1 ] d[r]-d[l-1] d[r]d[l1]来表示。假设区间 [ l , r ] [l, r] [l,r]的区间和为 s s s,由于 [ l , r ] [l, r] [l,r]区间和表示为 d [ r ] − d [ l − 1 ] d[r]-d[l-1] d[r]d[l1],也就是 r r r到根的距离与 l − 1 l-1 l1到根的距离之差,我们可以将 r r r所在并查集和 l − 1 l-1 l1所在并查集进行合并,为了方便表示不妨记录 t = l − 1 t=l-1 t=l1

合并前: s = d [ r ] − d [ t ] s=d[r]-d[t] s=d[r]d[t]

合并后: s = d [ r ] − ( d [ t ] + d [ p t ] ) s = d[r] - (d[t] + d[pt]) s=d[r](d[t]+d[pt])
d [ p t ] = d [ r ] − d [ t ] − s d[pt] = d[r] - d[t] - s d[pt]=d[r]d[t]s

将所有区间全部加入并查集后就可以直接利用类似前缀和的写法进行查询。

在查询时,如果 l − 1 l-1 l1 r r r不在同一个并查集当中,那么肯定是求不出来了,否则可以查询到结果。

🔑源代码

并查集实现时利用路径压缩增加效率。

java 代码:

import java.util.*;

class Main {
    static final int N = (int) 2e5 + 10;
    
    static int[] p = new int[N];
    static long[] d = new long[N];
    
    static Scanner sc = new Scanner(System.in);
    static int n, m, q;
    
    static int find(int x) {
        if (p[x] != x) {
            int t = p[x];
            p[x] = find(p[x]);
            d[x] += d[t];
        }   
        return p[x];
    }
    
    public static void main(String[] args) {
        n = sc.nextInt();
        m = sc.nextInt();
        q = sc.nextInt();
        
        //init uf
        for (int i = 1; i <= n; i++) p[i] = i;
        
        while (m-- > 0) {
            int l = sc.nextInt();
            int r = sc.nextInt();
            long s = sc.nextLong();
            int pt = find(l - 1), pr = find(r);
            p[pt] = pr;
            //更新d[pt]
            d[pt] = d[r] - s - d[l - 1];
        }
        
        while (q-- > 0) {
            int l = sc.nextInt();
            int r = sc.nextInt();
            
            int pt = find(l - 1), pr = find(r);
            if (pt != pr) System.out.println("UNKNOWN");
            else System.out.println(d[r] - d[l - 1]);
        }
    }
}

c++代码:

//带权并查集 与算法基础课中的食物链较像
//以一个根结点为参照,l-1到根结点的距离为d[l-1] r到根结点的距离为d[r]
//根据前缀和原理 [l, r] 区间和为 d[r] - d[l - 1]
#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;
typedef long long LL;
const int N = (int) 2e5 + 10;

//并查集 
int p[N];
//到根的权重
LL d[N];

int n, m, q;

int find(int x) 
{
    if (p[x] != x) 
    {
        int t = p[x];
        p[x] = find(p[x]);
        d[x] += d[t];
    }
    return p[x];
}

int main() 
{
    cin >> n >> m >> q;
    //初始化并查集
    for (int i = 1; i <= n; i++) p[i] = i;
    while (m-- > 0) 
    {
        LL l, r, s;
        cin >> l >> r >> s;
        
        //找根结点
        int pl = find(l - 1), pr = find(r);
        //合并
        p[pl] = pr;
        d[pl] = d[r] - d[l - 1] - s;
    }
    
    //查询
    //如果l, r都在同一个集合,则存在结果,否则不能查出结果
    while (q-- > 0) 
    {
        int l, r;
        
        cin >> l >> r;
        int pl = find(l - 1), pr = find(r);
        
        if (pl != pr) cout << "UNKNOWN" << endl;
        else cout << d[r] - d[l - 1] << endl;
    }
    
    return 0;
}

🌱总结

本题思维难度较大,带权并查集的思路并不好想。


觉得文章写得不错的老铁们,点赞评论关注走一波!谢谢啦!

有关【2022年蓝桥杯真题之带权并查集问题】推导部分和的更多相关文章

  1. 映宇宙2022年营收63亿元:同比下降三成,毛利率提升4.3个百分点 - 2

    3月26日,映宇宙(HK:03700,即“映客”)发布截至2022年12月31日的2022年度业绩财务报告。财报显示,映宇宙2022年的总营收为63.19亿元,较2021年同期的91.76亿元下降31.1%。2022年,映宇宙的经营亏损为4698.7万元,2021年同期则为净利润4.57亿元;期内亏损(净亏损)为1.68亿元,2021年同期的净利润为4.33亿元;非国际财务报告准则经调整净利润为3.88亿元,2021年同期为4.82亿元,同比下降19.6%。 映宇宙在财报中表示,收入减少主要是由于行业竞争加剧,该集团对旗下产品采取更为谨慎的运营策略以应对市场变化。不过,映宇宙的毛利率则有所提升

  2. 华为OD机试真题 C++ 实现【带传送阵的矩阵游离】【2023 Q2 | 200分】 - 2

            所有题目均有五种语言实现。C实现目录、C++实现目录、Python实现目录、Java实现目录、JavaScript实现目录题目n行m列的矩阵,每个位置上有一个元素你可以上下左右行走,代价是前后两个位置元素值差的绝对值.另外,你最多可以使用一次传送阵(只能从一个数跳到另外一个相同的数)求从走上角走到右下角最少需要多少时间。输入描述:第一行两个整数n,m,分别代表矩阵的行和列。后面n行,每行m个整数,分别代表矩阵中的元素。输出描述:一个整数,表示最少需要多少时间。

  3. 蓝桥杯备赛(二) - 2

    目录前言: 一、ASC分析代码实现二、 卡片分析代码实现三、 直线分析代码实现四、货物摆放分析代码实现小结:前言:  在刷题的过程中,发现蓝桥杯的题目和力扣的差别很大。让人有一种不一样的感觉,蓝桥杯题目偏向对于实际问题用编程去的解决,而力扣给人感觉很锻炼自己的编程思维,逻辑能力。两者结合去刷,相信会有不一样的收获。 一、ASC  已知大写字母A的ASCII码为65,请问大写字母L的ASCII码是多少?分析  这道题目看上去很简单,我们需确定自己计算的准确,所以我建议用编程去解决。代码实现publicclassTest8{publicstaticvoidmain(String[]args){Sy

  4. 蓝桥杯C/C++VIP试题每日一练之报时助手 - 2

    ?作者主页:静Yu?简介:CSDN全栈优质创作者、华为云享专家、阿里云社区博客专家,前端知识交流社区创建者?社区地址:前端知识交流社区?博主的个人博客:静Yu的个人博客?博主的个人笔记本:前端面试题个人笔记本只记录前端领域的面试题目,项目总结,面试技巧等等。接下来会更新蓝桥杯官方系统基础练习的VIP试题,依然包括解题思路,源代码等等。问题描述:给定当前的时间,请用英文的读法将它读出来。时间用时h和分m表示,在英文的读法中,读一个时间的方法是:  如果m为0,则将时读出来,然后加上“o’clock”,如3:00读作“threeo’clock”。  如果m不为0,则将时读出来,然后将分读出来,如5

  5. IDEA 2022 创建 Spring Boot 项目详解 - 2

    如何用IDEA2022创建并初始化一个SpringBoot项目?目录如何用IDEA2022创建并初始化一个SpringBoot项目?0. 环境说明1.  创建SpringBoot项目 2.编写初始化代码0. 环境说明IDEA2022.3.1JDK1.8SpringBoot1.  创建SpringBoot项目        打开IDEA,选择NewProject创建项目。        填写项目名称、项目构建方式、jdk版本,按需要修改项目文件路径等信息。        选择springboot版本以及需要的包,此处只选择了springweb。        此处需特别注意,若你使用的是jdk1

  6. 十四届蓝桥青少组模拟赛Python-20221108 - 2

    十四届蓝桥青少组模拟赛Python-20221108T1.二进制位数十进制整数2在十进制中是1位数,在二进制中对应10,是2位数。十进制整数22在十进制中是2位数,在二进制中对应10110,是5位数。请问十进制整数2022在二进制中是几位数?print(len(bin(2022))-2)#运行结果:11T2.晨跑小蓝每周六、周日都晨跑,每月的1、11、21、31日也晨跑。其它时间不晨跑。已知2022年1月1日是周六,请问小蓝整个2022年晨跑多少天?#样例代码1ls=[0,31,28,31,30,31,30,31,31,30,31,30,31]ans=0k=6foriinrange(1,13)

  7. 2022年10月23日周赛ZZULIOJ - 2

    文章目录问题B:芝华士威士忌和他的小猫咪们代码&注释问题C:愿我的弹雨能熄灭你们的痛苦代码注释问题D:猜糖果游戏代码注释问题E:有趣的次方代码注释问题F:这是一个简单题代码&注释问题G:打印矩阵代码注释问题H:scz的简单考验代码注释问题I:完美区间代码&注释问题J:是狂热的小迷妹一枚吖~代码&注释2022年10月23日周赛ZZULIOJ问题B:芝华士威士忌和他的小猫咪们时间限制:1Sec内存限制:128MB题目描述芝华士威士忌很喜欢带着他的猫咪们一块跑着玩。但是小猫咪们很懒,只有在离他y米以内才愿意和他一块跑。这天他在坐标为x的位置,他想和他的猫咪们一块跑着玩。有n个小猫咪,第i个小猫咪在坐

  8. 【华为OD机试真题 java、python、c++】荒地电站建设【2022 Q4 100分】(100%通过+复盘思路) - 2

    代码请进行一定修改后使用,本代码保证100%通过率,本题目提供了java、python、c++三种代码。复盘思路在文章的最后题目描述祖国西北部有一片大片荒地,其中零星的分布着一些湖泊,保护区,矿区;整体上常年光照良好,但是也有一些地区光照不太好。某电力公司希望在这里建设多个光伏电站,生产清洁能源对每平方公里的土地进行了发电评估,其中不能建设的区域发电量为0kw,可以发电的区域根据光照,地形等给出了每平方公里年发电量x千瓦。我们希望能够找到其中集中的矩形区域建设电站,能够获得良好的收益。输入描述第一行输入为调研的地区长,宽,以及准备建设的电站【长宽相等,为正方形】的边长最低要求的发电量之后每行为

  9. 蓝桥杯 stm32 MCP4017 - 2

    本文代码使用HAL库。文章目录前言一、MCP4017的重要特性二、MCP4017计算RBW阻值三、MCP4017地址四、MCP4017读写函数五、CubeMX创建工程(利用ADC测量MCP4017电压)、对应代码:总结前言一、MCP4017的重要特性蓝桥杯板子上的是MCP4017T-104ELT,如图1。MCP4017是一个可编程电阻,通过写入的数值可以改变电阻的大小。重点在于6引脚(W),5引脚(B&#

  10. [蓝桥杯单片机]学习笔记——串口通信的基本原理与应用 - 2

    目录一、原理部分1、什么是串行通信(1)并行通信与串行通信(2)串行通信的制式(3)串行通信的主要方式  2、配置串口(1)SCON和PCON:串行口1的控制寄存器(2)SBUF:串行口数据缓冲寄存器 (3)AUXR:辅助寄存器​编辑(4)ES、PS:与串行口1中断相关的寄存器(5)波特率设置  3、串口框架编写二、程序案例一、原理部分1、什么是串行通信(1)并行通信与串行通信微控制器与外部设备的数据通信,根据连线结构和传送方式的不同,可以分为两种:并行通信和串行通信。并行通信:数据的各位同时发送与接收,每个数据位使用一条导线,这种方式传输快,但是需要多条导线进行信号传输。串行通信:数据一位一

随机推荐