并查集-方法论-题解
区间覆盖问题
染色体染色,问每个的最后颜色是什么
- 参考
给定 M MM 次染色序列,问最后所有位置的颜色是什么?如果从前向后考虑,后边的染色会覆盖之前的一种染色,可以倒着考虑,如果一段区间已经染色就不再被染色了 (每个位置只会被染色一次) ,然后跳过一些状态,进行优化。
重要判据:fa[i] = i表示这个节点 / 物品,还没有出现过,或者还没有被染色过1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31int n,m,p,q;
int fa[1000010];
int a[1100000];
int ans[1100000];
int find(int x){// 找到从x开始的右边的第一个没有被染色的元素
return fa[x] == x ? fa[x] : fa[x] = find(fa[x]);
}
void solve(){
cin>>n>>m>>p>>q;
for(int i=1;i<=1000010;i++){
fa[i] = i;
}
while(m){
int l = (m*p+q)%n+1;
int r = (m*q+p)%n+1;
if(l>r)swap(l,r);
// 【l,r】
int x = find(l);
while(x<=r){
// [l,x]
ans [x] = m;
fa[x] = find(x+1);
x = find(x);
}
m -- ; // 容易错
}
for(int i=1;i<=n;i++){
cout<<ans[i]<<endl;
}
}
密码生成
- 参考
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93#include <cfloat>
#include <iostream>
#include <vector>
#include <map>
#include <numeric>
#include <algorithm>
using namespace std;
int find(int start, vector<int>& pa)
{
// 这里find(pa[start], pa)是关键;find(start) 肯定不行;
// find(start+1),可以但是复杂度太高
return pa[start] == start ? start : pa[start] = find(pa[start], pa);
}
int main() {
int N, M;
cin >> N >> M;
int mod = 100000009;
long long ans = 0;
vector<int> pa(N+1, 0);
vector<int> nums(N, 0);
iota(pa.begin(), pa.end(), 0);
int L, R;
vector<pair<int, int>> rec;
for (int __ = 0; __ < M; __++)
{
int l, r;
cin >> l >> r;
rec.push_back({l, r});
}
while (M > 0)
{
L = rec[M-1].first;
R = rec[M-1].second;
if (L > R) swap(L, R);
int x = find(L, pa);
while (x <= R)
{
nums[x] = M;
// ans += (1ll * x * M)%mod;
pa[x] = find(x+1, pa);
x = find(x, pa);
}
M--;
}
for (int i = 1; i < N; i++)
{
ans += (1ll * i * nums[i])%mod;
ans %= mod;
}
cout << ans;
}
// 64 位输出请用 printf("%lld")
并查集-方法论-题解
http://example.com/2024/09/04/算法刷题/并查集-方法论-题解/