并查集区间染色,自行学习用
给你一个序列$a_1, a_2…a_n$,初值时全为$0$。
如果给你$m$次操作,每次让你将$[l, r]$区间修改为一个全新的$val$($0\leq val $,你可以选择修改或者不修改),让你求全部修改完之后,整个序列的总和最大
遍历的先后顺序
我们可以知道,只要我们先将$val$从大往小排序,然后再去遍历,那么每次修改完一个区间之后修改过的区间就可以不修改了,那么问题就转化的比较简单了
区间修改的并查集使用
比如我们染色的时候,将$l$到$r$染成1,那么每次我们就可以遍历这个区间,让第$i$个节点的父亲节点是$i + 1$,也就是每次我们遍历区间$l \cdots r$,如果$fa[i] = i$的我们为才进行染色,让后让$fa[i] = fa[i + 1]$,那么我们就可以将$l \cdots r$这个区间直接染色最后依次枚举跳跃即可
inline void mer(int x, int y) //区间合并
{
int fx = find(x);
int fy = find(y);
if (fx != fy)
fa[fx] = fy;
return;
}
for(int i = 1; i <= n + 1; i ++ ) fa[i] = i;//初始化遍历到n + 1
for(int i = 1; i <= m; i ++ )//输入m个区间和染色
{
int l, r, val;
scanf("%d%d%d", &l, &r, &val);
seg[i] = {l, r, val};
}
sort(seg + 1, seg + 1 + m);//利用结构体重载进行了val值从大到小的排序
for(int i = 1; i <= m; i ++ )
{
int l = seg[i].l, r = seg[i].r, val = seg[i].val;
for(int j = find(l); j <= r; j = find(j))
{
if(j == fa[j]) a[j] = val;
mer(j, j + 1);
}
}