并查集、树状数组

news2024/12/23 10:07:58

并查集、树状数组、线段树

  • 并查集
  • 树状数组
    • 树状数组1 (单点修改,区间查询)
    • 树状数组2 (单点查询,区间修改)

并查集

【模板】并查集

题目描述

如题,现在有一个并查集,你需要完成合并和查询操作。

输入格式

第一行包含两个整数 N , M N,M N,M ,表示共有 N N N 个元素和 M M M 个操作。

接下来 M M M 行,每行包含三个整数 Z i , X i , Y i Z_i,X_i,Y_i Zi,Xi,Yi

Z i = 1 Z_i=1 Zi=1 时,将 X i X_i Xi Y i Y_i Yi 所在的集合合并。

Z i = 2 Z_i=2 Zi=2 时,输出 X i X_i Xi Y i Y_i Yi 是否在同一集合内,是的输出
Y ;否则输出 N

输出格式

对于每一个 Z i = 2 Z_i=2 Zi=2 的操作,都有一行输出,每行包含一个大写字母,为 Y 或者 N

样例输入 #1

4 7
2 1 2
1 1 2
2 1 2
1 3 4
2 1 4
1 2 3
2 1 4

样例输出 #1

N
Y
N
Y

提示

对于 30 % 30\% 30% 的数据, N ≤ 10 N \le 10 N10 M ≤ 20 M \le 20 M20

对于 70 % 70\% 70% 的数据, N ≤ 100 N \le 100 N100 M ≤ 1 0 3 M \le 10^3 M103

对于 100 % 100\% 100% 的数据, 1 ≤ N ≤ 1 0 4 1\le N \le 10^4 1N104 1 ≤ M ≤ 2 × 1 0 5 1\le M \le 2\times 10^5 1M2×105 1 ≤ X i , Y i ≤ N 1 \le X_i, Y_i \le N 1Xi,YiN Z i ∈ { 1 , 2 } Z_i \in \{ 1, 2 \} Zi{1,2}

以下是模板代码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 10005

int fa[MAXN]; // 用于存储每个元素所属的集合的根节点

// 查找操作,返回元素x所属集合的根节点
int find(int x) {
	if(x == fa[x]) return x; // 如果当前节点是根节点,直接返回
	return fa[x] = find(fa[x]); // 路径压缩,将x的父节点直接设为根节点,加快以后的查找
}

// 合并操作,将两个集合合并
void join(int c1, int c2) {
	int f1 = find(c1); // 查找c1所属的集合的根节点
	int f2 = find(c2); // 查找c2所属的集合的根节点
	if(f1 != f2) // 如果根节点不同,表示c1和c2不在同一集合中
		fa[f1] = f2; // 将c1的根节点的父节点设为c2的根节点,即合并两个集合
}

int main() {
	int n, m;
	cin >> n >> m; // 输入元素个数n和操作个数m
	for(int i = 1; i <= n; i++) fa[i] = i; // 初始化,每个元素初始时都是一个单独的集合,根节点就是自己
	
	while(m--) {
		int z, x, y;
		cin >> z >> x >> y; // 输入操作类型z以及两个元素x和y
		
		if(z == 1) {
			join(x, y); // 合并操作,将x和y所在的集合合并
		} else {
			if(find(x) == find(y))
				cout << "Y" << endl; // 查找操作,如果x和y在同一个集合中,输出Y
			else
				cout << "N" << endl; // 否则输出N
		}
	}
	
	return 0;
}

树状数组

树状数组1 (单点修改,区间查询)

【模板】树状数组 1

题目描述

如题,已知一个数列,你需要进行下面两种操作:

  • 将某一个数加上 x x x

  • 求出某区间每一个数的和

输入格式

第一行包含两个正整数 n , m n,m n,m,分别表示该数列数字的个数和操作的总个数。

第二行包含 n n n 个用空格分隔的整数,其中第 i i i 个数字表示数列第 i i i 项的初始值。

接下来 m m m 行每行包含 3 3 3 个整数,表示一个操作,具体如下:

  • 1 x k 含义:将第 x x x 个数加上 k k k

  • 2 x y 含义:输出区间 [ x , y ] [x,y] [x,y] 内每个数的和

输出格式

输出包含若干行整数,即为所有操作 2 2 2 的结果。

样例输入 #1

5 5
1 5 4 2 3
1 1 3
2 2 5
1 3 -1
1 4 2
2 1 4

样例输出 #1

14
16

提示

【数据范围】

对于 30 % 30\% 30% 的数据, 1 ≤ n ≤ 8 1 \le n \le 8 1n8 1 ≤ m ≤ 10 1\le m \le 10 1m10
对于 70 % 70\% 70% 的数据, 1 ≤ n , m ≤ 1 0 4 1\le n,m \le 10^4 1n,m104
对于 100 % 100\% 100% 的数据, 1 ≤ n , m ≤ 5 × 1 0 5 1\le n,m \le 5\times 10^5 1n,m5×105

数据保证对于任意时刻, a a a 的任意子区间(包括长度为 1 1 1 n n n 的子区间)和均在 [ − 2 31 , 2 31 ) [-2^{31}, 2^{31}) [231,231) 范围内。

样例说明:

故输出结果14、16

以下是模板代码

#include<bits/stdc++.h>
using namespace std;
const int N = 5e5 + 5;
#define lowbit(x) ((x) & (-x))
int tree[N] = {0}; // 树状数组

void update(int x, int d) { // 单点修改:修改元素 a[x],a[x] = a[x] + d
	while (x <= N) {
		tree[x] += d; // 将当前位置的值增加d
		x += lowbit(x); // 转到下一个需要修改的位置
	}
}

int sum(int x) { // 查询前缀和:返回前缀和 sum = a[1] + a[2] + ... + a[x]
	int ans = 0;
	while (x > 0) {
		ans += tree[x]; // 累加当前位置的值
		x -= lowbit(x); // 转到前一个位置
	}
	return ans;
}

int main() {
	int n, m, a;
	cin >> n >> m; // 输入数列数字个数n和操作总个数m
	for (int i = 1; i <= n; i++) {
		cin >> a; // 输入每个数列项的初始值
		update(i, a); // 初始化计算tree[]数组
	}
	while (m--) {
		int op;
		cin >> op; // 输入操作类型
		if (op == 1) {
			int x, k;
			cin >> x >> k; // 输入要修改的元素位置x和要加的值k
			update(x, k); // 对位置x的元素进行加法操作
		} else {
			int x, y;
			cin >> x >> y; // 输入查询区间[x, y]
			cout << sum(y) - sum(x - 1) << endl; // 输出区间内元素和
		}
	}
	return 0;
}

树状数组2 (单点查询,区间修改)

【模板】树状数组 2

题目描述

如题,已知一个数列,你需要进行下面两种操作:

  1. 将某区间每一个数加上 x x x

  2. 求出某一个数的值。

输入格式

第一行包含两个整数 N N N M M M,分别表示该数列数字的个数和操作的总个数。

第二行包含 N N N 个用空格分隔的整数,其中第 i i i 个数字表示数列第 $i $ 项的初始值。

接下来 M M M 行每行包含 2 2 2 4 4 4个整数,表示一个操作,具体如下:

操作 1 1 1: 格式:1 x y k 含义:将区间 [ x , y ] [x,y] [x,y] 内每个数加上 k k k

操作 2 2 2: 格式:2 x 含义:输出第 x x x 个数的值。

输出格式

输出包含若干行整数,即为所有操作 2 2 2 的结果。

样例输入 #1

5 5
1 5 4 2 3
1 2 4 2
2 3
1 1 5 -1
1 3 5 7
2 4

样例输出 #1

6
10

提示

样例 1 解释:

故输出结果为 6、10。


数据规模与约定

对于 30 % 30\% 30% 的数据: N ≤ 8 N\le8 N8 M ≤ 10 M\le10 M10

对于 70 % 70\% 70% 的数据: N ≤ 10000 N\le 10000 N10000 M ≤ 10000 M\le10000 M10000

对于 100 % 100\% 100% 的数据: 1 ≤ N , M ≤ 500000 1 \leq N, M\le 500000 1N,M500000 1 ≤ x , y ≤ n 1 \leq x, y \leq n 1x,yn,保证任意时刻序列中任意元素的绝对值都不大于 2 30 2^{30} 230

以下是模板代码

#include<bits/stdc++.h>
using namespace std;
const int N = 5e5 + 5;
#define lowbit(x) ((x) & (-x))
int tree[N] = {0}; // 树状数组

void update(int x, int d) { // 单点修改:修改元素 a[x],a[x] = a[x] + d
	while (x <= N) {
		tree[x] += d; // 将当前位置的值增加d
		x += lowbit(x); // 转到下一个需要修改的位置
	}
}

int sum(int x) { // 查询前缀和:返回前缀和 sum = a[1] + a[2] + ... + a[x]
	int ans = 0;
	while (x > 0) {
		ans += tree[x]; // 累加当前位置的值
		x -= lowbit(x); // 转到前一个位置
	}
	return ans;
}

int main() {
	int n, m;
	int old = 0, a;
	cin >> n >> m; // 输入数列数字个数n和操作总个数m
	for (int i = 1; i <= n; i++) {
		cin >> a; // 输入每个数列项的初始值
		update(i, a - old); // 初始化计算tree[]数组,这里是一个差分数组
		old = a;
	}
	while (m--) {
		int op;
		cin >> op; // 输入操作类型
		if (op == 1) {
			int x, y, k;
			cin >> x >> y >> k; // 输入要修改的区间[x, y]和要加的值k
			update(x, k);
			update(y + 1, -k); // 将区间[y+1, n]的值减去k,保持区间[x, y]加上k
		} else {
			int x;
			cin >> x; // 输入要查询的位置x
			cout << sum(x) << endl; // 输出第x个数的值
		}
	}
	return 0;
}

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

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

相关文章

GIF制作器-gif动图制作助手、格式转换软件

GIF制作器​​​​​​​-无水印制作gif动态图片&#xff01; 一步轻松制作GIF&#xff0c;将视频、Live Photo、照片轻松转换成GIF动图&#xff0c;超级简单好用~ 【功能简介】 视频转GIFLive Photo转GIF图片转GIFGIF编辑 【编辑工具】 自由裁剪GIF内容调节GIF播放速度添加文…

C++ 网络编程项目fastDFS分布式文件系统(一)

目录 1.项目架构图 1.1 一些概念 1.2 项目架构图 2. 分布式文件系统 2.1 传统文件系统 2.2 分布式文件系统 3. FastDFS 3.1 fastDFS介绍 3.2 fastDFS安装 3.3 fastDFS配置文件 3.4 fastDFS的启动 4. fastDFS状态检测 4.1 对file_id的解释 4. 2上传下载代码实现 …

电流的测量(分流电流表)

在当今的大多数仪器应用中&#xff0c;可以使用两种常见的电流测量方法&#xff1a;分流电流表方法和反馈电流表方法。分流电流表方法通常与通用数字万用表 (DMM)一起使用&#xff0c;用于测量分流电阻器上的电压测量值。该电压测量结果与已知的电阻值相结合&#xff0c;得出电…

ADM2587E在RS485和RS422接口的应用(ADM2587E电路原理图和程序开发)

最近做一个项目使用到ADM2587E&#xff0c;为了解决公司历史遗留的问题&#xff08;ADM2587E芯片发烫&#xff0c;容易烧毁&#xff0c;485设备只能手拉手连接三四个&#xff0c;就通信不正常现象&#xff09;&#xff0c;认真阅读了Datasheet和官网LayOut的一些设计文档&#…

4、基于mysql实现分布式锁

目录 4.1. 基本思路4.2. 代码实现4.3 缺陷及解决方案 4.1. 基本思路 synchronized关键字和ReetrantLock锁都是独占排他锁&#xff0c;即多个线程争抢一个资源时&#xff0c;同一时刻只有一个线程可以抢占该资源&#xff0c;其他线程只能阻塞等待&#xff0c;直到占有资源的线程…

棒球和垒球的区别·棒球联盟

棒球和垒球的区别 1. 定义和起源 棒球起源于19世纪中叶的美国&#xff0c;最初被认为是一种游戏&#xff0c;而并非体育运动。那时&#xff0c;棒球常常被孩子们用来进行休闲娱乐。在20世纪初&#xff0c;它才开始被纳入体育运动的范畴。 垒球则是棒球的近亲&#xff0c;同样…

Java | 字符串

目录 一、String类 1.1 声明字符串 1.2 创建字符串 二、连接字符串 2.1 连接多个字符串 2.2 连接其他数据类型 三、获取字符串信息 3.1 获取字符串长度 3.2 字符串查找 3.3 获取指定索引位置的字符 四、字符串操作 4.1 获取字符串 4.2 去除空格 4.3 字符串替换 …

Android JNI开发从0到1,java调C,C调Java,保姆级教程详解

前些天发现了一个蛮有意思的人工智能学习网站,8个字形容一下"通俗易懂&#xff0c;风趣幽默"&#xff0c;感觉非常有意思,忍不住分享一下给大家。 &#x1f449;点击跳转到教程 第一步首先配置Android studio的NDK开发环境&#xff0c;首先在Android studio中下载NDK…

QT-基于Buildroot构建系统镜像下实现QT开发

QT-基于Buildroot构建系统镜像下实现QT开发 BuildRootUboot的仓库地址和commit idKernel 的仓库地址和commit id BuildRoot已编译库在Windows上的Create上创建项目编译QT项目 BuildRoot 这部分按照100ask官网的教程走即可: Uboot的仓库地址和commit id https://e.coding.net/…

如何使用ChatGPT设计LOGO,只需知道品牌名字就能完成傻瓜式操作

​独特且引人注目的LOGO对于引导用户/消费者快速识别并与你建立联系至关重要。然而&#xff0c;聘请专业的设计师来创建个性化LOGO可能非常昂贵。这里可以使用使用ChatGPT。[1] 你只需要&#xff1a; 准备好公司名称&#xff1b; 能用ChatGPT&#xff0c;用来给BingChat喂log…

WebAPIs 第一天

1.声明变量const优先&#xff08;补充&#xff09; 2.WebAPI基本认知 作用和分类 DOM树和DOM对象 3.获取DOM元素 4.DOM修改元素内容 5.操作元素属性 6.定时器-间歇函数 一.声明变量const优先 ① 变量声明有var let const ② 建议const优先&#xff0c;尽量使用const…

【枚举+推式子】牛客小白月赛 63 E

登录—专业IT笔试面试备考平台_牛客网 题意&#xff1a; 思路&#xff1a; 首先是个计数问题&#xff0c;考虑组合数学 组合数学就是在考虑枚举所有包含1和n的区间 这个典中典就是枚举1和n的位置然后算贡献 双指针超时&#xff0c;考虑推式子&#xff1a; Code&#xff1a…

分类过程中的一种遮挡现象

( A, B )---3*30*2---( 1, 0 )( 0, 1 ) 让网络的输入只有3个节点&#xff0c;AB训练集各由6张二值化的图片组成&#xff0c;让A&#xff0c;B中各有3个点&#xff0c;且不重合&#xff0c;统计迭代次数并排序。 其中有10组数据 差值结构 迭代次数 构造平均列A 构造平均列AB…

C++笔记之函数参数列表中设置默认值

C笔记之函数参数列表中设置默认值 code review! 代码 #include <iostream>// 函数声明时设置默认值 void printInfo(std::string name "Unknown", int age 0);int main() {printInfo(); // 使用默认参数值printInfo("Alice", 25);…

Scractch3.0_Arduino_ESP32_学习随记_蓝牙鼠标(四)

蓝牙鼠标 目的器材程序联系我们 目的 通过C02实现蓝牙鼠标。 器材 硬件: 齐护机器人C02 购买地址 软件:scratch3.0 下载地址:官网下载 程序 蓝牙鼠标使用使用ESP32自带的BLE蓝牙&#xff0c;不需要再外接模块。可以实现鼠标移动&#xff0c;左右键的点击动作。 联系我们…

C++进阶 智能指针

本篇博客简介&#xff1a;介绍C中的智能指针 智能指针 为什么会存在智能指针内存泄露内存泄漏定义内存泄漏的危害如何检测内存泄漏如何避免内存泄漏 智能指针的使用及其原理RAII设计一个智能指针C官方的智能指针 定制删除器智能指针总结 为什么会存在智能指针 我们首先来看下面…

消息队列(11) - 通信协议的设计

目录 通信协议设计代码实现 通信协议设计 对于我们客户端与服务器之间的通信协议我们约定如下&#xff1a; 具体的协议设计: 之后我们传递的参数也是这些 关于 type其实是在描述当前这个请求 、 响应是在调用那个API 约定如下 对于channel ,是tcp链接中的一个逻辑上的链接,…

Python实现图片文本支持中文,自定义字体

Python实现图片文本支持中文&#xff0c;自定义字体 # 支持中文 import matplotlib #用下载好的字体文件设置字体&#xff0c;从而正确显示中文 myfont matplotlib.font_manager.FontProperties(fnamer"./simsun.ttc") # 自定义的字体文件 plt.figure(figsize (1…

udp一般不会存在错数据

UDP在传输过程中会出现丢包的情况&#xff0c;但不会导致数据错乱的情况&#xff0c;这涉及到UDP协议的特性和工作原理。 无连接性&#xff1a;UDP是一种无连接的传输协议&#xff0c;每个UDP数据包都是独立的&#xff0c;没有依赖关系。因此&#xff0c;即使发生数据包丢失&am…

Golang 局部变量、全局变量 声明

文章目录 一、局部变量二、全局变量 一、局部变量 四种声明方式 多变量声明&#xff1a; package mainimport "fmt"//局部变量声明 func main() {//方法一: 声明一个变量和数据类型&#xff0c;不初始化值&#xff1b;默认值为0&#xff1b;var lvA intfmt.Printl…