@@ -108,26 +108,221 @@ tags:
108108
109109<!-- solution:start -->
110110
111- ### 方法一
111+ ### 方法一:并查集 + 有序集合
112+
113+ 我们可以使用并查集(Union-Find)来维护电站之间的连接关系,从而确定每个电站所属的电网。对于每个电网,我们使用有序集合(如 Python 中的 ` SortedList ` 、Java 中的 ` TreeSet ` 或 C++ 中的 ` std::set ` )来存储该电网中所有在线的电站编号,以便能够高效地查询和删除电站。
114+
115+ 具体步骤如下:
116+
117+ 1 . 初始化并查集,处理所有连接关系,将连接的电站合并到同一个集合中。
118+ 2 . 为每个电网创建一个有序集合,初始时将所有电站编号加入对应电网的集合中。
119+ 3 . 遍历查询列表:
120+ - 对于查询 $[ 1, x] $,首先找到电站 $x$ 所属的电网根节点,然后检查该电网的有序集合:
121+ - 如果电站 $x$ 在线(存在于集合中),则返回 $x$。
122+ - 否则,返回集合中的最小编号电站(如果集合非空),否则返回 -1。
123+ - 对于查询 $[ 2, x] $,找到电站 $x$ 所属的电网根节点,并将电站 $x$ 从该电网的有序集合中删除,表示该电站离线。
124+ 4 . 最后,返回所有类型为 $[ 1, x] $ 的查询结果。
125+
126+ 时间复杂度 $O((c + n + q) \log c)$,空间复杂度 $O(c)$。其中 $c$ 是电站数量,而 $n$ 和 $q$ 分别是连接数量和查询数量。
112127
113128<!-- tabs:start -->
114129
115130#### Python3
116131
117132``` python
118-
133+ class UnionFind :
134+ def __init__ (self , n ):
135+ self .p = list (range (n))
136+ self .size = [1 ] * n
137+
138+ def find (self , x ):
139+ if self .p[x] != x:
140+ self .p[x] = self .find(self .p[x])
141+ return self .p[x]
142+
143+ def union (self , a , b ):
144+ pa, pb = self .find(a), self .find(b)
145+ if pa == pb:
146+ return False
147+ if self .size[pa] > self .size[pb]:
148+ self .p[pb] = pa
149+ self .size[pa] += self .size[pb]
150+ else :
151+ self .p[pa] = pb
152+ self .size[pb] += self .size[pa]
153+ return True
154+
155+
156+ class Solution :
157+ def processQueries (
158+ self , c : int , connections : List[List[int ]], queries : List[List[int ]]
159+ ) -> List[int ]:
160+ uf = UnionFind(c + 1 )
161+ for u, v in connections:
162+ uf.union(u, v)
163+ st = [SortedList() for _ in range (c + 1 )]
164+ for i in range (1 , c + 1 ):
165+ st[uf.find(i)].add(i)
166+ ans = []
167+ for a, x in queries:
168+ root = uf.find(x)
169+ if a == 1 :
170+ if x in st[root]:
171+ ans.append(x)
172+ elif len (st[root]):
173+ ans.append(st[root][0 ])
174+ else :
175+ ans.append(- 1 )
176+ else :
177+ st[root].discard(x)
178+ return ans
119179```
120180
121181#### Java
122182
123183``` java
124-
184+ class UnionFind {
185+ private final int [] p;
186+ private final int [] size;
187+
188+ public UnionFind (int n ) {
189+ p = new int [n];
190+ size = new int [n];
191+ for (int i = 0 ; i < n; ++ i) {
192+ p[i] = i;
193+ size[i] = 1 ;
194+ }
195+ }
196+
197+ public int find (int x ) {
198+ if (p[x] != x) {
199+ p[x] = find(p[x]);
200+ }
201+ return p[x];
202+ }
203+
204+ public boolean union (int a , int b ) {
205+ int pa = find(a), pb = find(b);
206+ if (pa == pb) {
207+ return false ;
208+ }
209+ if (size[pa] > size[pb]) {
210+ p[pb] = pa;
211+ size[pa] += size[pb];
212+ } else {
213+ p[pa] = pb;
214+ size[pb] += size[pa];
215+ }
216+ return true ;
217+ }
218+ }
219+
220+ class Solution {
221+ public int [] processQueries (int c , int [][] connections , int [][] queries ) {
222+ UnionFind uf = new UnionFind (c + 1 );
223+ for (int [] e : connections) {
224+ uf. union(e[0 ], e[1 ]);
225+ }
226+
227+ TreeSet<Integer > [] st = new TreeSet [c + 1 ];
228+ Arrays . setAll(st, k - > new TreeSet<> ());
229+ for (int i = 1 ; i <= c; i++ ) {
230+ int root = uf. find(i);
231+ st[root]. add(i);
232+ }
233+
234+ List<Integer > ans = new ArrayList<> ();
235+ for (int [] q : queries) {
236+ int a = q[0 ], x = q[1 ];
237+ int root = uf. find(x);
238+
239+ if (a == 1 ) {
240+ if (st[root]. contains(x)) {
241+ ans. add(x);
242+ } else if (! st[root]. isEmpty()) {
243+ ans. add(st[root]. first());
244+ } else {
245+ ans. add(- 1 );
246+ }
247+ } else {
248+ st[root]. remove(x);
249+ }
250+ }
251+
252+ return ans. stream(). mapToInt(Integer :: intValue). toArray();
253+ }
254+ }
125255```
126256
127257#### C++
128258
129259``` cpp
130-
260+ class UnionFind {
261+ public:
262+ UnionFind(int n) {
263+ p = vector<int >(n);
264+ size = vector<int >(n, 1);
265+ iota(p.begin(), p.end(), 0);
266+ }
267+
268+ bool unite(int a, int b) {
269+ int pa = find(a), pb = find(b);
270+ if (pa == pb) {
271+ return false;
272+ }
273+ if (size[pa] > size[pb]) {
274+ p[pb] = pa;
275+ size[pa] += size[pb];
276+ } else {
277+ p[pa] = pb;
278+ size[pb] += size[pa];
279+ }
280+ return true;
281+ }
282+
283+ int find(int x) {
284+ if (p[x] != x) {
285+ p[x] = find(p[x]);
286+ }
287+ return p[x];
288+ }
289+
290+ private:
291+ vector<int > p, size;
292+ };
293+
294+ class Solution {
295+ public:
296+ vector<int > processQueries(int c, vector<vector<int >>& connections, vector<vector<int >>& queries) {
297+ UnionFind uf(c + 1);
298+ for (auto& e : connections) {
299+ uf.unite(e[ 0] , e[ 1] );
300+ }
301+
302+ vector<set<int>> st(c + 1);
303+ for (int i = 1; i <= c; i++) {
304+ st[uf.find(i)].insert(i);
305+ }
306+
307+ vector<int > ans;
308+ for (auto & q : queries) {
309+ int a = q[0], x = q[1];
310+ int root = uf.find(x);
311+ if (a == 1) {
312+ if (st[root].count(x)) {
313+ ans.push_back(x);
314+ } else if (!st[root].empty()) {
315+ ans.push_back(*st[root].begin());
316+ } else {
317+ ans.push_back(-1);
318+ }
319+ } else {
320+ st[root].erase(x);
321+ }
322+ }
323+ return ans;
324+ }
325+ };
131326```
132327
133328#### Go
0 commit comments