并查集 + 离线 ( O(n) 做法 )
2023-12-21 19:14:49
发布于:广东
120阅读
0回复
0点赞
离线 + 并查集
- 因为后面的 染色 优先级更大,所以将 染色 操作 存起来,然后 倒序 处理。(离线操作)
- 那么对于后来的染色[L,R], 如果前面的染色已经包含了[L,R],则丢弃,否则要找出[L,R]中未被染色的区间。
- 用并查集 fa[i] 表示 i 位置左边最近未染色的位置是哪里,对于 find(R) < L的 染色 直接丢弃(已经被包含) , 否则 染色 find(R) ,同时令 fa[find(R)] = find(L-1) (表示染色到 L ) , 然后 沿着 find(R)-1走上述过程就行了。
可以证明,每个点只会被染色一次,所以时间复杂度是 O(n)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5+5;
int fa[maxn];//表示左边离自己最近未染色的点在哪
int find(int x){
return fa[x] == x?x:fa[x] = find(fa[x]);
}
int n,m;
int l[maxn],r[maxn],col[maxn];
int ans[maxn];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)fa[i]=i;//初始化,开始自己未染色
for(int i=1;i<=m;i++){
scanf("%d%d%d",&l[i],&r[i],&col[i]);
if(l[i]<1)l[i] = 1;// 数据有0
if(r[i]>n)r[i] = n;// 数据有>n
}
for(int i=m;i>=1;i--){
if( find(r[i]) < l[i] )continue;// 颜色被覆盖
for(int j = find(r[i]); j>=l[i];j = find(j-1) ){// 沿着未染色的点走进行染色
ans[j] = col[i];
fa[find(j)] = find(l[i]-1);//染完色的点祖先都是find(l[i]-1)的祖先
}
}
for(int i=1;i<=n;i++)printf("%d ",ans[i]);
return 0;
}
全部评论 1
冒泡
2024-12-07 来自 广东
0
有帮助,赞一个