【题解·C/C++】并查集的灵活使用题目,洛谷P1196 [NOI2002] 银河英雄传说

news/2024/10/18 6:07:19/

题目简介

给出两种指令:M和C。
M i j:将 i i i 插入到 j j j 的末尾,按照顺序将整个序列插入。
C i j:查询 i i i j j j 节点之间的元素个数。
洛谷P1196跳转链接

解题思路

首先注意到,如果有节点p,而它的子节点l1,l2,l3的father都是p。
那么我们只需要修改p,l1,l2,l3的值就可以顺便修改了(类似LazyTag延迟更新),当查询到l1,l2,l3头上的时候,再去更新。

现在设计三个数组:Index、Fa、Nums数组。

第一个Index数组用于保存此节点全局的编号。第二个保存这个节点的爸爸。而第三个保存的是此节点往后的所有元素个数。

比如序列【(1)、(2)、(3)】节点的Index是1,2,3

而序列【(4)、(5)】节点Index是1,2

那么现在想要【(4)、(5)、(1)、(2)、(3)】的话,正确的节点Index应该是,1,2,3,4,5但是现在却是1,2,1,2,3。

好在,我们的(2)、(3)指向(1)因为(1)是他们爸爸。而(5)指向(4)。并查集合并的时候使用(1)指向(4)然后因为知道了【(1),(2),(3)】元素的个数,所以可以修改Nums[(4)]=2(之前是两个元素)+3(又加入3个元素);

然后可以修改全局索引Index[(1)]=3,因为我们知道之前的Nums[(4)]有两个。所以说,现在是1,2,3,2,3。

那么后面两个2,3怎么更正呢?通过查询自己父节点Index[(1)]=3,可以知道如果它之前没有链接其他序列,它应该是Index[(1)]=1,所以我们知道偏移量是2。因为头部多了两个元素,所以,后面的肯定也是两个元素。在Query的过程中,就可以轻松更正Index[(2)]=2+2=4查询(3)的时候也可以轻松更正Index[(3)]=3+2=5.

所以最后:【(4)、(5)、(1)、(2)、(3)】的整个全局的Index是:1,2,3,4,5。啦!

现在,你已经知道了,整个序列元素是5个·,也知道了Index的编号,那么Nums还不好更新吗?So Easy了~找找关系就好啦!

(っ °Д °;)っ

AC代码

// VsCode C++模板 | (●'◡'●)
#include <bits/stdc++.h>#include <iostream>
using namespace std;
typedef long long LL;
#define MaxN 30000 + 5
int T, Index[MaxN], Fa[MaxN], Nums[MaxN];
int QueryRoot(int node) {if (Fa[node] == node) { return node; }auto root = QueryRoot(Fa[node]);int& node_root = Fa[node]; // now rootint _move = Index[node_root] - 1;Index[node] += _move;Nums[node] = Nums[root] - Index[node] + 1;node_root = root;return root;
}
void Mergen(int i, int j) {int rootI = QueryRoot(i);int rootJ = QueryRoot(j);Index[rootI] += Nums[rootJ];Nums[rootJ] += Nums[rootI];Fa[rootI] = rootJ;
}
int main() {for (int i = 1;i <= MaxN - 5;i++) {Index[i] = 1;Nums[i] = 1;Fa[i] = i;}scanf("%d", &T);while (T--) {char opt; int i, j;cin >> opt >> i >> j;if (opt == 'M') { //MergMergen(i, j);} else { //Queryint rootI = QueryRoot(i), rootJ = QueryRoot(j);if (rootI != rootJ) printf("-1\n"); else {printf("%d\n", abs(Index[i] - Index[j]) - 1);}}}return 0;
}

http://www.ppmy.cn/news/63359.html

相关文章

恐怖,又要有多少人下岗!AI零成本设计主图,渗入10万亿电商市场

在电商平台上&#xff0c;主图是吸引消费者点击进入商品详情页的重要因素之一。 一张高点击的电商主图&#xff0c;不仅要能够吸引消费者的眼球&#xff0c;还要能够清晰地展示产品的特点和卖点。下面是一些制作高点击电商主图的建议。 1. 突出产品特点&#xff1a;在制作主图…

淄博烧烤,怎么就“出圈”了-也是机器视觉行业职场中的态度:少一点套路,多一些真诚,少一点计较,多一些宽容

我认为淄博烧烤之所以火爆&#xff0c;是因为它代表了一种淄博人的态度&#xff0c;一种对生活的热爱和对客人的真诚。 我认为淄博烧烤之所以火爆&#xff0c;是因为它代表了一种淄博人的态度&#xff0c;一种对生活的热爱和对客人的真诚。 我想更重要的一点&#xff0c;淄博烧…

Vue电商项目--开发Search模块与mockjs模拟数据

Search模块中商品分类与过度动画 现在完成了在/home路由下实现三级导航组件的显示隐藏 通过this.$route.path!/home在搜索页面显示&#xff0c;通过方法鼠标移入移出从而又控制在search路由下的显示隐藏 过渡动画&#xff1a;前提组件|元素必要又v-if| v-show指令才可以进行…

鸿蒙Hi3861学习八-Huawei LiteOS-M(事件标记)

一、简介 事件是一种实现任务间通信的机制&#xff0c;可用于实现任务间的同步。但事件通信只能是事件类型的通信&#xff0c;无数据传输。一个任务可以等待多个事件的发生&#xff1a;可以是任意一个事件发生时唤醒任务进行事件处理&#xff1b;也可以是几个事件都发生后才唤醒…

Java设计模式(七)桥接模式

一、概述 桥接模式是一种结构型设计模式&#xff0c;它将抽象部分与实现部分分离&#xff0c;使它们可以独立变化。桥接模式通过将抽象和实现进行解耦&#xff0c;让它们可以独立地扩展和变化&#xff0c;同时可以在运行时动态地将不同的抽象和实现组合起来。 二、代码 下面…

遗传算法(GA)

理论&#xff1a; 遗传算法是一种通过模拟生物进化的方式来寻找最优解的一类优化算法。这种算法主要依靠遗传、突变和自然选择的机制对问题求解进行高效的迭代搜索。 遗传算法的基本思想是将问题的解表示成一个个个体&#xff0c;然后根据适应度函数的定义来评估每个个体的适…

【设计模式】建造者模式

【设计模式】建造者模式 参考资料&#xff1a; 重学 Java 设计模式&#xff1a;实战建造者模式「各项装修物料组合套餐选配场景」 建造者模式——链式调用 五分钟彻底了解建造者模式 文章目录 【设计模式】建造者模式一、建造者模式介绍1.1、定义1.2、角色概述 二、案例场景模…

Acid burn(★★)

运行程序 先是弹出一个neg 然后是真正的程序界面 有一个输入Serial和Name的判断 还有一个只输入Serial的判断 查壳 没有壳&#xff0c;是Delphi程序 先除去一个Neg 找到Neg弹出的程序&#xff0c;在程序头下个断&#xff0c;运行程序&#xff0c;此时栈顶是调用此功能的…