经典模型——并查集解决区间/树链染色问题

蒟蒻的第一篇blog


模型背景:

已知一个长度为n的序列,开始时序列的每一个元素都没有颜色(0),现进行m次操作,第i次操作将一段区间[l,r]中还未被染色的点(即a[i]=0的点)染成颜色i.问m次操作后这个区间长什么样子,并将它输出来.

数据规模约定:对于100%的数据,n,m<=10^6

问题解决

  1. 我会nm暴力!

对于每一个操作i,暴力扫描[l,r],染色,最后输出.

※期望得分:10.

  1. 并查集!没想到吧

用并查集来维护从节点i往后的区间[i,n]中第一个0出现的位置,也就是i之后第一个还未被染色的点的位置.

这是怎么做到的呢?

一开始每个节点的father显然指向自己(所有点都没染色).如果这个点被染了色,就将它与它的右边第一个点union起来,即father[i] = father[i+1].
比如:

经过几次之后的染色以及一番奇妙的路径压缩,序列将形成类似这种样子

这样,不就给下一次的操作省时间了吗,不就能一跳就跳到下一个0的地方染色了吗(欣喜)

核心代码:

int findfather(int x) {//找下一个为0的点,顺便路径压缩
    if (father[x] != x)
        father[x] = findfather(father[x]);
    return father[x];
}

inline int combine(int x, int y) {//union
    int fx = findfather(x);
    int fy = findfather(y);
    if (fx != fy)
        father[fx] = fy;
    return;
}

int main() {
    /*读入等操作略*/
    for (int i = 1; i <= m; ++i) {//染色
        for (int j = findfather(l); j <= r; j = findfather(j)) {
            color[j] = i;
        }
    }
    /*输出操作略*/
}

怎么样,是不是很好懂呢?

然而,

如果是要对树上的链进行染色的话,又该如何做呢?

  1. 这不就是树链剖分吗,上树剖啊

嗯,看起来就好像 【模板】树链剖分 的简化版.但是请回头看一眼数据范围.嗯,由于树剖的时间瓶颈在于线段树,树剖显然无法解决10^6级别的数据

期望得分:80.

  1. 并查集!没想到吧

对于树上的一条链(u,v),除了通过树链剖分来处理以外,我们还可以通过将这条链分割成(u,LCA),(LCA,v)来解决.类比之前对于一段序列的做法,我们可以改进出这样的做法:

问题解决

在上一个模型中,我们发现了一种从一个点直接跳到下一个未染色的点的方法,那就是用并查集+路径压缩不断往右指.这个问题也一样.当一个点被染色时,我们可以将它的并查集数组指向它的父节点(即father[i]=fa[i],father[i]是i节点的并查集数组,fa[i]是它在题目中树上的父亲节点).

接下来就可以类比之前的问题了.若要给(3,5)染色,就由深度大的开始往上跳,不过这个跳是findfather那种跳(雾).

问题解决了吗?

实际跳的时候会发现,它可能会跳到LCA以上的地方!

你会发现,如果2之前被染过色,那么路径压缩的时候会直接将3的father连到1上!

因此需要加一些特判,不让它往高处跳.

还有不懂的地方的话,就来看代码吧XD:

/*我个人比较喜欢借助树链剖分来求LCA,也可以采用其他方法*/

int findfather(int x) //略

inline void combine(int x, int y) //略

inline int LCA(int x, int y) //略

inline void paint(int x, int y, int c) {
    int lca = LCA(x, y);
    while (x != y) {
        if (dep[x] < dep[y])
            swap(x, y);//每次让深度大的向上跳
        x = dep[findfather(x)] < dep[lca] ? lca : father[x];//特判,阻止X往上方跳
        col[x] = c, combine(x, fa[x]);
    }
    return;
}

这样问题就解决了!

欢迎指正和批评!

原文地址:https://www.cnblogs.com/i-cookie/p/11383767.html

时间: 2024-11-05 02:33:06

经典模型——并查集解决区间/树链染色问题的相关文章

并查集-解决区间和纠错问题 hdu-3038

题目:多次给出信息,告诉你[a,b]区间的和,求多少个错误信息(错误信息不考虑). 乍一看有点像线段树,但想想就发现这个并不能用线段树方便地解决.后来经提醒是并查集的一种经典题型. 把区间抽象为并查集的子节点和母根结点,子节点存放了到根节点的区间和.这样当引入一个新的区间,如果区间左右界根节点不同就一定不存在矛盾(有点种类并查集的意思,形象来看就是存在冗余区间用于调整),然后可以通过现存集合推导出子节点到根节点的区间和.如果根节点相同则要判断一下是否矛盾(画个图对线段加加减减就能推出公式了,文字

Codeforces Round #423 (Div. 2) C 思维,并查集 或 线段树 D 树构造,水

Codeforces Round #423 (Div. 2, rated, based on VK Cup Finals) C. String Reconstruction   思维,并查集 或 线段树 题意:一个字符串被删除了,但给出 n条信息,要还原出可能的字典序最小的字符串.信息有:字符串ti,ki个位置xi,表明原本的字符串在xi位置是以字符串ti开头的. tags:惨遭 fst,一开始把所有字符串都存下来,排序做的,结果爆内存了.. 方法1: 考虑并查集,对于字符串 ti,在位置xi,

HDU 1512 并查集+左偏树

Monkey King Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3105    Accepted Submission(s): 1330 Problem Description Once in a forest, there lived N aggressive monkeys. At the beginning, they e

poj2513——判断是否为欧拉图(并查集,trie树)

POJ 2513    Colored Sticks 欧拉回路判定,并查集,trie树 Time Limit: 5000MS   Memory Limit: 128000K Total Submissions: 31621   Accepted: 8370 Description You are given a bunch of wooden sticks. Each endpoint of each stick is colored with some color. Is it possibl

并查集+欧拉回路+字典树 Colored Sticks POJ 2513

输入多组数据,每组数据两种颜色,表示一根木头两端的颜色,现在要将这些木头相连,要求相连部分颜色相同,问能否全部连通 提示 1)一个要判断所有的木头是否在一个集合中,即是否能相连 2)判断一种颜色出现的数量 3)一棵树如果只有0或2个点出现次数为奇数,则树可以一笔画成 #include <stdio.h> #include <string.h> #define maxn 500005 int tot; int f[maxn]; int num[maxn]; struct trie {

poj 1611 :The Suspects经典的并查集题目

Severe acute respiratory syndrome (SARS), an atypical pneumonia of unknown aetiology, was recognized as a global threat in mid-March 2003. To minimize transmission to others, the best strategy is to separate the suspects from others.   In the Not-Spr

ACM学习历程—SNNUOJ 1110 传输网络((并查集 &amp;&amp; 离线) || (线段树 &amp;&amp; 时间戳))(2015陕西省大学生程序设计竞赛D题)

Description Byteland国家的网络单向传输系统可以被看成是以首都 Bytetown为中心的有向树,一开始只有Bytetown建有基站,所有其他城市的信号都是从Bytetown传输过来的.现在他们开始在其他城市陆 续建立了新的基站,命令“C x“代表在城市x建立了一个新的基站,不会在同一个城市建立多个基站:城市编号为1到n,其中城市1就是首都Bytetown.在建立基站的过程中他们还 会询问某个城市的网络信号是从哪个城市传输过来的,命令”Q x“代表查询城市x的来源城市. Inpu

UVA 572 油田连通块-并查集解决

题意:8个方向如果能够连成一块就算是一个连通块,求一共有几个连通块. 分析:网上的题解一般都是dfs,但是今天发现并查集也可以解决,为了方便我自己理解大神的模板,便尝试解这道题目,没想到过了... 1 #include <cstdio> 2 #include <iostream> 3 #include <sstream> 4 #include <cmath> 5 #include <cstring> 6 #include <cstdlib&

Knight Tournament 伪并查集(区间合并)

Knight Tournament Hooray! Berl II, the king of Berland is making a knight tournament. The king has already sent the message to all knights in the kingdom and they in turn agreed to participate in this grand event. As for you, you're just a simple pea