并查集:推导部分和

这篇具有很好参考价值的文章主要介绍了并查集:推导部分和。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

推导部分和

问题描述

对于一个长度为 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 = A l i + A l i + 1 + ⋯ + A r i \sum_{j=l_{i}}^{r_{i}}=A_{l_{i}}+A_{l_{i}+1}+\cdots+A_{r_{i}} j=liri=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 ≤ 10000 1 \leq N, M, Q \leq 50,-10000 \leq S_{i} \leq 10000 1N,M,Q50,10000Si10000

对于 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 0 9 1 \leq N, M, Q \leq 10000,-10^{9} \leq S_{i} \leq 10^{9} 1N,M,Q10000,109Si109

对于所有评测用例, 1 ≤ N , M , Q ≤ 1 0 5 , − 1 0 12 ≤ S i ≤ 1 0 12 , 1 ≤ l i ≤ r i ≤ N 1 \leq N, M, Q \leq 10^{5},-10^{12} \leq S_{i} \leq 10^{12}, 1 \leq l_{i} \leq r_{i} \leq N 1N,M,Q105,1012Si1012,1liriN, 1 ≤ l ≤ r ≤ N 1 \leq l \leq r \leq N 1lrN 。数据保证没有矛盾。

解题思路一 加权并查集

灵光一闪:部分和+重复
(多次求部分和最快方法——前缀和)
给出指定区间 [ l , r ] [l,r] [l,r] 的部分和,根据前缀和的思想,若下标 l , r l,r l,r 处的前缀和分别为 S l , S r S_{l},S_{r} Sl,Sr ,那么区间 [ l , r ] [l,r] [l,r] 的部分和可表示为 S r − S l − 1 S_{r}-S_{l-1} SrSl1.
问题
不知道数组全貌,没办法求完整的前缀和
基本情况
给出指定区间 [ l , r ] [l,r] [l,r] 的部分和,问我们区间 [ l , r ] [l,r] [l,r]的部分和
简单延申
给出指定区间 [ l , r ] [l,r] [l,r] [ r , r + k ] [r,r+k] [r,r+k]的部分和,问我们区间 [ l , r + k ] [l,r+k] [l,r+k]的部分和
发现
l指向r,r指向r+k,结果两两组合都可以求出来部分和——并查集

注意:由于部分和的值始终为编号较小的结点 d i s [ l ] dis[l] dis[l] 与编号较大的结点 d i s [ r ] dis[r] dis[r] 间的差值,因此对于一个结点 i i i ,若其并查集祖宗结点 j j j 的编号大于 i i i ,那么 d i s [ i ] dis[i] dis[i] 记录的距离为 s s s ,否则,记录的是 s s s 的负数。例如,结点 4 到 5 的距离为 6 ,那么结点 5 到结点 4 的距离为 -6 。
步骤
1、初始化:需要将并查集数组有效部分的长度初始化为 n + 1 n+1 n+1 ,
2、合并:对于每个输入的区间端点 l , r l,r l,r 和部分和 s s s ,并查集结点 l − 1 l-1 l1 r r r 之间的距离为 s s s, 结点合并时,并查集的权数组 d i s dis dis 维护 s s s.
3、将所有的区间和进行并查集连通后,对输入的需要求解的区间和 [ q l , q r ] [ql,qr] [ql,qr] 进行判断,如果 q l , q r ql,qr ql,qr 有相同的祖宗结点,那么 d i s [ q l ] − d i s [ q r ] dis[ql]-dis[qr] dis[ql]dis[qr] 即为区间和。否则,说明 q l , q r ql,qr ql,qr 并不连通,此时无法求出区间和。文章来源地址https://www.toymoban.com/news/detail-503924.html

AC Code(Python3)

# -*- coding: utf-8 -*-
# @Author : BYW-yuwei
# @Software: python3.8.6
N=int(1e5)+10

father=[0]*N
dis=[0]*N
def init(n:int):
    for i in range(1,n+1):
        father[i]=i
def find_father(x:int):
    if father[x]==x:return x
    t=father[x]   
    father[x]=find_father(father[x])
    dis[x]+=dis[t]                      #权重数组dis维护两个结点间的距离,此题为区间和
    return father[x]
def unite(x:int,y:int,w:int):
    fx=find_father(x); fy=find_father(y)
    if fx==fy:return
    father[fx]=fy
    dis[fx]=dis[y]-dis[x]+w         #合并时维护节点间的区间和(fx>fy则为负值,fx<fy则为正值)

if __name__=='__main__':
    n,m,q=map(int,input().split())
    init(n)                         #对加权并查集初始化
    for i in range(m):
        l,r,s=map(int,input().split())
        l-=1                        #类似前缀和,[l,r]的和为l-1到r的距离
        unite(l,r,s)                #合并结点l与r
    res=[]                          #存放结果的列表
    for i in range(q):
        ql,qr=map(int,input().split())
        ql-=1                       #与l情况相同
        faql=find_father(ql); faqr=find_father(qr)
        if(faql!=faqr):res.append("UNKNOWN")    #两个结点不连通,此时的和不可求解
        else:res.append(dis[ql]-dis[qr])  #部分和为两结点间dis的差值(由前缀和性质,部分和一定是左边区间减右边区间)
    for item in res:
        print(item)

到了这里,关于并查集:推导部分和的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 【高阶数据结构】——并查集

    【高阶数据结构】——并查集

    在一些应用问题中, 需要将n个不同的元素划分成一些不相交的集合。开始时,每个元素自成一个单元素集合, 然后按一定的规律将归于同一组元素的集合合并 。在此过程中要 反复用到查询某一个元素归属于那个集合的运算 。适合于描述这类问题的抽象数据类型称为 并查集

    2024年02月16日
    浏览(13)
  • 修改数组【并查集】

    修改数组【并查集】

    并查集就是对集合的合并和查询操作的统称。他要求参与运算的两个集合是不相交的(不含有相同的元素)。针对这两个集合可以进行的操作: 1.合并:将两个集合合并成一个集合。 2.查询:查询给定的两个元素是不是在同一个集合中。 每一个并查集都使用一个树来表示,数的

    2024年02月07日
    浏览(11)
  • 数据结构---并查集

    数据结构---并查集

    这里可以使用生活中的一个例子来带着大家理解并查集,大家在上学的过程中肯定会发现一种现象,在开学之前大家谁也不认识谁每个人都是一个小团体,可是开学之后因为座位旁边有一个同桌,所以开学没多久你和同桌就会互相认识并且开心的玩在一起,那么这时就是两个

    2024年02月15日
    浏览(14)
  • 【数据结构】并查集

    【数据结构】并查集

    并查集是简单的数据结构,学会并查集,为图打好基础。 是树状的数据结构,用于处理相交集合的合并与查询 通常用森林表示,一片森林表示一个集合 并查集一般需要完成 查找元素属于哪个集合 查看两个元素是否属于同一个集合 将两个集合归并成一个集合 集合的个数 假

    2024年02月19日
    浏览(11)
  • C++:合并集合(并查集)

    一共有n个数,编号是1~n,最开始每个数各自在一个集合中。 现在要进行m个操作,操作共有2种: 1.“M a b”,将编号为a和b的两个数的所在的集合合并,如果两个数已经在同一个集合中则忽略这个操作 2.“Q a b”,询问编号为a和b的两个数是否在同一个集合中 第一行输入整数

    2024年02月13日
    浏览(13)
  • 高阶数据结构 ——— 并查集

    高阶数据结构 ——— 并查集

    并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题。 并查集通常用森林来表示,森林中的每棵树表示一个集合,树中的结点对应一个元素。 说明一下: 虽然利用其他数据结构也能完成不相交集合的合并及查询,但在数据量极大的情况下,其耗费的时

    2024年02月03日
    浏览(23)
  • 【数据结构】--并查集

    【数据结构】--并查集

    目录 一、概念 ​编辑 二、应用场景--“连接”问题(属于同一Qu 三、实现思路  四、如何存储数据 五、定义接口 1.初始化(init) 2.其他 isSame() 六、抽象类 六、Quick Find【v1 所在集合的所有元素都指向 v2 的根节点】 1.Union 1.Union图解 2.注意点:  3.代码实现 2.find  1.find图

    2023年04月09日
    浏览(10)
  • 并查集の进阶用法

    我们在处理问题的时候,可能会遇到一些需要维护每个元素所在的集合的问题,而并查集却恰好完美解决了这个问题。 对于普通的并查集,他支持的操作比较少,只有合并和查询,合并是指把两个集合合并成一个,而查询是询问两个元素是否在同一集合内;对于这两种操作,

    2024年02月02日
    浏览(13)
  • 并查集

    并查集

    并查集 并查集是用来判断两个元素是否属于同一个集合 即判断他们的根节点是否相同 1. 初始化 2.查询根节点 3.合并 集合变为一个长长的链时,查找变得十分麻烦,此时我们需要路径压缩 即每个人的直接根节点就是最上面的根节点 我们判断两个元素是否是同一个集合,看的

    2024年02月08日
    浏览(9)
  • 数据结构--并查集

    数据结构--并查集

    所有元素的全集s 将各个元素划分为若干个互不相交的子集 用一个数组S[ ]即可表示“集合”关系 集合的两个基本操作―— “并” color{red}“并” “ 并 ” 和 “查” color{red}“查” “ 查 ” Find -—“查”操作:确定一个指定元素所属集合 Union --“并”操作:将两个不想交的集

    2024年02月15日
    浏览(11)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包