并查集经典应用之染色模型
思路:
由于一个点最后的颜色取决于最后一次染色,那么我们可以倒着染色, 每染色一个点就将这个点删掉并记录颜色。
用ptr[i] 表示第i 个元素后面第一个未被覆盖的区间
当我们覆盖一个点i 的时候,就把i的指针ptr 向后移动到i+1 的指针指向的位置(指针跳跃)
这样就不会重复覆盖一个点
另外需要注意的是,对于点n+1,我们需要初始化它的指针,否则会无限调用ptr:因为ptr[n+1]=0,而p[0]=0。不过我们也可以通过初始化所有ptr避免这个问题
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1000010;
int n, m, p, q;
int color[N], ptr[N];
void init()
{
for(int i = 0; i < N; i ++ ) ptr[i] = i;
}
int find(int x)
{
if(ptr[x] == x) return x;
return ptr[x] = find(ptr[x]);
}
int main()
{
init();
cin >> n >> m >> p >> q;
for(int i = m; i >= 1; i -- )//倒着染色
{
int a = (i * p + q) % n + 1, b = (i * q + p) % n + 1;
int r = max(a, b), l = min(a, b);//处理一下顺序
int pa = find(l);//找到指针指向的点
while(pa <= r)
{
color[pa] = i;//染色
ptr[pa] = find(pa + 1);//指针跳跃
pa = ptr[pa];//下一个点
}
}
//卡常数,输出必须用scanf
for(int i = 1; i <= n; i ++ ) printf("%d\n", color[i]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】