Skip to content

Commit 273de84

Browse files
Merge pull request #4244 from envyaims/sussy
cf 2set
2 parents 22a7670 + 47be752 commit 273de84

File tree

2 files changed

+134
-13
lines changed

2 files changed

+134
-13
lines changed

content/4_Gold/DSU.problems.json

+12-13
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,18 @@
9898
"solutionMetadata": {
9999
"kind": "internal"
100100
}
101+
},
102+
{
103+
"uniqueId": "cf-468B",
104+
"name": "Two Sets",
105+
"url": "https://codeforces.com/contest/468/problem/B",
106+
"source": "CF",
107+
"difficulty": "Normal",
108+
"isStarred": false,
109+
"tags": ["DSU"],
110+
"solutionMetadata": {
111+
"kind": "internal"
112+
}
101113
}
102114
],
103115
"harder": [
@@ -138,19 +150,6 @@
138150
"kind": "internal"
139151
}
140152
},
141-
{
142-
"uniqueId": "cf-468B",
143-
"name": "Two Sets",
144-
"url": "https://codeforces.com/contest/468/problem/B",
145-
"source": "CF",
146-
"difficulty": "Hard",
147-
"isStarred": false,
148-
"tags": ["DSU", "2SAT"],
149-
"solutionMetadata": {
150-
"kind": "autogen-label-from-site",
151-
"site": "CF"
152-
}
153-
},
154153
{
155154
"uniqueId": "onlinejudgeorg-war",
156155
"name": "War",

solutions/gold/cf-468B.mdx

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
---
2+
id: cf-468B
3+
source: CF
4+
title: Two Sets
5+
author: Chongtian Ma
6+
---
7+
8+
<Spoiler title="Hint 1">
9+
10+
We can model the two sets as a graph, with $p_i$ and $a - p_i$ connected in graph $A$, and $p_i$ connected to $b - p_i$ in graph B.
11+
12+
</Spoiler>
13+
14+
<Spoiler title="Hint 2">
15+
16+
How can there be a contradiction in the connected components?
17+
18+
</Spoiler>
19+
20+
## Explanation
21+
22+
We can treat each set as a graph with several connected components. For each $p_i$, if $a - p_i$ exists, then $p_i$ and $a - p_i$ are in the same connected component inside graph $A$, and similarly for $B$. Each number in the connected component must belong to one set. Therefore, our condradiction comes from if there is a number $x$ in the component such that only $a - x$ exists, and another $y$ in the component such that only $b - y$ exists, or vice cersa.
23+
24+
We can check each component for the contradiction using DSU. The status of the whole component will be the intersection of what graph each number in the component can reside in.
25+
26+
## Implementation
27+
28+
**Time Complexity:** $\mathcal{O}(N\log N)$
29+
30+
<LanguageSection>
31+
<CPPSection>
32+
33+
```cpp
34+
#include <bits/stdc++.h>
35+
using namespace std;
36+
37+
// BeginCodeSnip{DSU (from the module)}
38+
class DSU {
39+
private:
40+
vector<int> parents;
41+
vector<int> sizes;
42+
43+
public:
44+
DSU(int size) : parents(size), sizes(size, 1) {
45+
for (int i = 0; i < size; i++) { parents[i] = i; }
46+
}
47+
48+
int get(int x) {
49+
return parents[x] == x ? x : (parents[x] = get(parents[x]));
50+
}
51+
52+
bool unite(int x, int y) {
53+
int x_root = find(x);
54+
int y_root = find(y);
55+
if (x_root == y_root) { return false; }
56+
57+
if (sizes[x_root] < sizes[y_root]) { swap(x_root, y_root); }
58+
sizes[x_root] += sizes[y_root];
59+
parents[y_root] = x_root;
60+
return true;
61+
}
62+
};
63+
// EndCodeSnip
64+
65+
int main() {
66+
int n, a, b;
67+
cin >> n >> a >> b;
68+
vector<int> p(n);
69+
for (int i = 0; i < n; i++) { cin >> p[i]; }
70+
71+
map<int, int> at;
72+
for (int i = 0; i < n; i++) { at[p[i]] = i; }
73+
74+
DSU dsu(n);
75+
vector<int> can_A(n), can_B(n);
76+
for (int i = 0; i < n; i++) {
77+
if (at.count(a - p[i])) {
78+
can_A[i] = true;
79+
dsu.unite(i, at[a - p[i]]);
80+
}
81+
if (at.count(b - p[i])) {
82+
can_B[i] = true;
83+
dsu.unite(i, at[b - p[i]]);
84+
}
85+
}
86+
87+
/*
88+
* first bit activated if all numbers in component i can reside in
89+
* graph A, and similarly the second bit for graph B
90+
*/
91+
vector<int> can_component(n, 3);
92+
for (int i = 0; i < n; i++) {
93+
int mask = 0;
94+
if (can_A[i]) mask += 1;
95+
if (can_B[i]) mask += 2;
96+
can_component[dsu.get(i)] &= mask;
97+
}
98+
99+
for (int i = 0; i < n; i++) {
100+
if (!can_component[i]) {
101+
cout << "NO" << endl;
102+
return 0;
103+
}
104+
}
105+
106+
cout << "YES" << endl;
107+
for (int i = 0; i < n; i++) {
108+
int comp_mask = can_component[dsu.get(i)];
109+
if (comp_mask == 1) {
110+
// only can be in set A
111+
cout << 0 << " ";
112+
} else {
113+
// can be in either set A or B
114+
cout << 1 << " ";
115+
}
116+
}
117+
cout << endl;
118+
}
119+
```
120+
121+
</CPPSection>
122+
</LanguageSection>

0 commit comments

Comments
 (0)