Mayor‘s posters--线段树染色

这篇博客探讨了一维和二维染色问题的解决方法,利用线段树优化算法,将一维的n次操作优化到log n的时间复杂度。在一维问题中,通过区间修改和lazy propagation实现;在二维问题中,通过将纵坐标离散化并为相邻纵边区间建立线段树,将问题转化为一维染色,总时间复杂度为O(n log n)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一维染色问题

这一类题目,一般都有一个固定的样式,当你对题目进行简化以后,总会得到类似与下面这种模型类似:

在一条数轴上,依次进行n次操作,每次操作读入3个数,x,y,z,表示在区间[x,y]中涂上颜色z,后涂上的颜色会覆盖之前涂上的颜色。问最后我们还能看到几种颜色,是哪几种,所覆盖的长度分别为多少?(1≤x≤y≤1e5,n≤1e5)

对于这种题目,初次见到这种题目的同学可能会一脸懵逼,毫无头绪。首先我们先观察一下数据范围,嗯,1≤x≤y≤1e5,n≤1e5,普通的暴力算法复杂度达到了O(n^2),是我们所不能接受的,这个时候,我们就可以考虑怎么样用线段树优化掉一维的n变为log n。

我们考虑可以对于从前往后进行染色,每一次染色都当作一次区间修改,每次强行进行区间修改染色,最后将线段树从上向下的pushup一下,把标记全部下传到根节点就好了

假如我们初始的空白线段长度为8,我们先新开一棵线段树:(注意建树时每个节点的是否被染色的标记都要初始化)
在这里插入图片描述
第一次操作,我们把[3,5]染成红色,按照区间修改的思路,把完全覆盖的区间改为红色,并且打上lazy标记:
在这里插入图片描述
第二次操作,我们把[5,8]染成绿色,按照区间修改的思路,把完全覆盖的区间改为绿色,并且打上lazy标记:
在这里插入图片描述
第三次操作,我们把[8,8]染成黄色,在经过绿色标记是时,我们有标记的点下传后再进行操作,按照区间修改的思路,把完全覆盖的区间改为黄色,并且打上lazy标记:
在这里插入图片描述

最后一次操作,把[1,4]染成紫色,按照区间修改的思路,把完全覆盖的区间改为紫色,并且打上lazy标记:

在这里插入图片描述
在操纵完成后,我们自上而下把标记全部下传到叶子节点就是最后序列的样子了:
在这里插入图片描述

金典题目:Mayor’s posters
注意一组数据

3
3
5 6
4 5
6 8
3
1 10
1 3
6 10

5
1 4
2 6
8 10
3 4
7 10
正确答案应该是:
2
3
4

首先要离散化但要注意上面指出的样例
简单的来说就是再距离大2的两个点中间加入一个点防止中间有染色区间在离散化后不出现的情况

#include<iostream>
#include<algorithm>
#include<set>
#include<vector>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>pll;
typedef pair<int, int>pii;
const ll N = 1e6 + 5;
const ll MOD = 998244353;
const ll INF = 0x7fffffff;
int w[N];
struct node {
   
    int l, r;
    int color;//区间染色的情况,0为未染色
} tree[N << 2];
void push_down(int root) {
   //下放染色懒标记
    if (tree[root
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值