news 2026/5/22 1:59:40

一类并查集维护的区间染色问题

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
一类并查集维护的区间染色问题

并查集的区间染色

并查集作为一种高级数据结构,可以高效地维护元素与元素,元素与集合之间的关系。

在一些涉及到区间染色的题中,并查集可以很好地维护块的大小,块的边界和块的合并。

以例题来做具体解释。

[CF356A Knight Toumament](Problem - A - Codeforces)

题意

� 个骑士编号从 1 到 �,给出 � 场决斗。每场决斗给出 �,�,� 表示区间 [�,�] 之间还没被打败的骑士之间进行决斗,编号为 � 的骑士获得胜利。数据保证最后只有一个骑士获得胜利,对于每个骑士,输出打败他的骑士的编号,特别的,最后胜利的骑士输出 0。

  • 2≤�≤3⋅105
  • 1≤�≤3⋅105

思路

这道题的关键在于快速找出 [�,�] 之间还在场上的骑士。

对于每个被打败的骑士,向右边连一条边,遍历时只会在没有被打败的骑士处停下来。这里使用并查集加上路径压缩就能取得很优秀的复杂度。

要找到下一个骑士只需要继续遍历右边的一块就行,这里会把胜利的骑士也一同处理了,所以在最后把胜利的骑士的父亲再设置为自己就行了。

复杂度大约为 �(��)

具体思路在代码中有讲解。

代码

#include <bits/stdc++.h>
using namespace std;
const int N = 3e5+50;
int n,m,l,r,x,f[N],ans[N];
inline int Find(int x)
{
if(f[x]!=x)f[x]=Find(f[x]);
return f[x];
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n+1;i++)f[i]=i;
while(m--)
{
cin>>l>>r>>x;
int now=Find(l); //找到第一个仍在场上的骑士
while(now<=r) //超出范围就停止
{
ans[now]=x; //被 x 打败
f[now]=now+1; //向右连边
now=Find(now);//找下一个,这里要注意只能从 now 和后面的位置开始找
} //如果当前为 x 的话从左边找会破坏路径,直接跳过 x
f[x]=x;
}
for(int i=1;i<=n;i++)cout<<(i==ans[i]?0:ans[i])<<' ';
cout<<'\n';
return 0;
}

ABC380E 1D Bucket Tool

题意

有 � 个格子排成一行,初始时第 � 个格子的颜色为 �。有 � 次操作,操作 1 给出 �,�,将格子 � 与和 � 同色的色块染成 �。操作 2 给出 �,询问颜色为 � 的格子的数量。

  • 1≤�≤5⋅105
  • 1≤�≤2⋅105

思路

考虑用并查集怎么做。

如果当前块右边的一块的颜色与当前块相同,就把当前块的父亲设置为右边的一块。这样每次遍历停下的点就是该极色块的右端点。

对于操作 1 ,先要找到最大的一块,因为可能左右两块颜色相同但是并未相连,由于每次是在右端点停,对于右边一块直接找右端点的右边一个就行,这里还要维护左端点这个信息来向左扩展。

合并两个块时,左边的块的父亲设置为右边的块,更新大小和左边界。

直到无法扩展再更新颜色,这里要记录每种颜色的块原本有多少个,然后直接加减就行。

对于操作 2,直接输出记录的数量就行。

代码

#include <bits/stdc++.h>
using namespace std;
const int N = 5e5+50;
int n,q,c[N],f[N],siz[N],cnt[N],L[N];
inline int Find(int x)
{
if(f[x]!=x)f[x]=Find(f[x]);
return f[x];
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>q;
for(int i=1;i<=n;i++)c[i]=i,f[i]=i,siz[i]=1,L[i]=i,cnt[i]=1;
while(q--)
{
int op;cin>>op;
if(op==1)
{
int x,C;cin>>x>>C;
int rt=Find(x);
while(c[rt]==c[Find(L[rt]-1)]) //向左扩展
{
int to=Find(L[rt]-1);
f[to]=rt; //左边合并到右边
siz[rt]+=siz[to];
L[rt]=L[to];
}
while(c[rt]==c[Find(rt+1)]) //向右扩展
{
int to=Find(rt+1);
f[rt]=to;
siz[to]+=siz[rt];
L[to]=L[rt];
rt=to;
}
cnt[c[rt]]-=siz[rt]; // 最后更新每种颜色的小块的数量
cnt[C]+=siz[rt];
c[rt]=C;
}
else
{
int x;cin>>x;
cout<<cnt[x]<<'\n';
}
}
return 0;
}

小结

对于区间染色,并查集做到的实际上是快速跳过已经被合并的元素来降低复杂度,对于一些区间能够合并或者是元素会被消除的题,不妨考虑一下能否使用并查集。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/1 18:16:38

MinerU实战指南:从零部署到高效PDF转Markdown的完整流程

1. MinerU工具简介与核心优势 PDF文档处理一直是技术文档管理中的痛点问题&#xff0c;特别是当我们需要将PDF转换为可编辑的Markdown格式时&#xff0c;传统方法往往束手无策。MinerU作为一款开源PDF解析工具&#xff0c;彻底改变了这一局面。它不仅能将PDF转换为结构化的Mark…

作者头像 李华
网站建设 2026/4/1 18:13:51

tchMaterial-parser:突破教育资源壁垒的电子课本下载革新方案

tchMaterial-parser&#xff1a;突破教育资源壁垒的电子课本下载革新方案 【免费下载链接】tchMaterial-parser 国家中小学智慧教育平台 电子课本下载工具&#xff0c;帮助您从智慧教育平台中获取电子课本的 PDF 文件网址并进行下载&#xff0c;让您更方便地获取课本内容。 项…

作者头像 李华
网站建设 2026/4/1 18:12:48

企业级Java系统AI化落地:基于稳定框架的集成与生态赋能

html 在企业级软件开发领域&#xff0c;Java技术栈凭借其成熟的生态体系、高稳定性和广泛的应用场景&#xff0c;长期占据着核心地位。随着人工智能技术的快速迭代&#xff0c;尤其是大模型的普及&#xff0c;传统Java系统面临着AI能力接入、存量系统改造、多模型适配以及业务…

作者头像 李华
网站建设 2026/4/1 18:12:08

51单片机入门-直流电机(十五)

目录&#xff1a;1.直流电机驱动&#xff08;PWM&#xff09;2.LED呼吸灯&直流电机调速1.直流电机驱动&#xff08;PWM&#xff09;让他转的快一些让他转2us停1us2.LED呼吸灯&直流电机调速点亮一个LED&#xff1a;在循环里&#xff1a;点亮熄灭显示暗一些&#xff1a;让…

作者头像 李华
网站建设 2026/4/1 18:11:05

3步颠覆窗口管理:RBTray系统托盘化完全指南

3步颠覆窗口管理&#xff1a;RBTray系统托盘化完全指南 【免费下载链接】rbtray A fork of RBTray from http://sourceforge.net/p/rbtray/code/. 项目地址: https://gitcode.com/gh_mirrors/rb/rbtray 你是否也曾经历过这样的场景&#xff1a;任务栏被十几个窗口图标占…

作者头像 李华