Skip to content

Commit e13becc

Browse files
committed
dodano rozwiązanie zadania 'Strajki' z XXIV OI
1 parent ba21dc4 commit e13becc

File tree

3 files changed

+199
-0
lines changed

3 files changed

+199
-0
lines changed
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// Rozwiązanie zadania 'Strajki' z II etapu XXIV OI.
2+
// Autor: Paweł Putra
3+
// Złożoność czasowa: O(n + m * log(n)).
4+
// Złożoność pamięciowa: O(n).
5+
6+
#include <iostream>
7+
#include <vector>
8+
#include <queue>
9+
#include <cassert>
10+
using namespace std;
11+
constexpr int MAXN = 1'000'005, INF = 1'000'000'005;
12+
int n, m;
13+
int vis[MAXN], strajk[MAXN], t[MAXN], L[MAXN], R[MAXN], par[MAXN];
14+
vector<int> g[MAXN];
15+
16+
struct Fenwick {
17+
int n;
18+
vector<int> fw;
19+
20+
Fenwick(int n) : n(n), fw(n, 0) {}
21+
22+
void add(int x, int delta) {
23+
for (;x < n; x |= x + 1)
24+
fw[x] += delta;
25+
}
26+
int sum(int r) {
27+
int res = 0;
28+
for (; r >= 0; r = (r & (r + 1)) - 1)
29+
res += fw[r];
30+
return res;
31+
}
32+
int sum(int l, int r) {
33+
if (l > r) return 0;
34+
return sum(r) - sum(l-1);
35+
}
36+
};
37+
38+
int32_t main() {
39+
ios_base::sync_with_stdio(0);
40+
cin >> n;
41+
42+
for (int i = 1; i < n; i++) {
43+
int a, b;
44+
cin >> a >> b;
45+
assert(a < b);
46+
g[a].push_back(b);
47+
g[b].push_back(a);
48+
}
49+
50+
int T = 0;
51+
52+
// Ukorzeniamy drzewo w jedynce i numerujemy je w kolejności przechodzenia bfsem,
53+
// dzięki temu synowie wierzchołka zajmują spójny przedział numerów.
54+
queue<int> q;
55+
q.push(1);
56+
t[1] = ++T;
57+
while (!q.empty()) {
58+
int v = q.front();
59+
q.pop();
60+
L[v] = INF, R[v] = -INF;
61+
for (auto u : g[v]) {
62+
if (!t[u]) {
63+
t[u] = ++T;
64+
par[u] = v;
65+
L[v] = min(L[v], t[u]);
66+
R[v] = max(R[v], t[u]);
67+
q.push(u);
68+
}
69+
}
70+
}
71+
72+
73+
int spojne = 1;
74+
Fenwick fw(n+2);
75+
cin >> m;
76+
while (m--) {
77+
int v;
78+
cin >> v;
79+
if (v > 0) {
80+
assert(!strajk[v]);
81+
} else {
82+
v = -v;
83+
assert(strajk[v]);
84+
}
85+
86+
strajk[v] = 1 - strajk[v];
87+
int ile = (R[v] >= L[v] ? (R[v] - L[v] + 1) - fw.sum(L[v], R[v]) : 0);
88+
if (par[v] && !strajk[par[v]]) ile++;
89+
90+
if (strajk[v]) {
91+
spojne += ile - 1;
92+
fw.add(t[v], 1);
93+
} else {
94+
spojne -= ile - 1;
95+
fw.add(t[v], -1);
96+
}
97+
98+
cout << spojne << "\n";
99+
}
100+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// Rozwiązanie brutalne do zadania 'Strajki' z II etapu XXIV OI.
2+
// Autor: Paweł Putra
3+
// Złożoność czasowa: O(m * n)
4+
// Złożonośc pamięciowa: O(n)
5+
#include <iostream>
6+
#include <vector>
7+
#include <queue>
8+
#include <cassert>
9+
using namespace std;
10+
constexpr int MAXN = 1'000'005;
11+
int n, m;
12+
int vis[MAXN], strajk[MAXN];
13+
vector<int> g[MAXN];
14+
15+
void bfs(int s, int kolor) {
16+
vis[s] = kolor;
17+
queue<int> q;
18+
q.push(s);
19+
while (!q.empty()) {
20+
int v = q.front();
21+
q.pop();
22+
for (auto u : g[v]) {
23+
if (vis[u] != kolor && !strajk[u]) {
24+
vis[u] = kolor;
25+
q.push(u);
26+
}
27+
}
28+
}
29+
}
30+
31+
int policz_spojne() {
32+
static int K = 0;
33+
K++;
34+
int spojne = 0;
35+
for (int i = 1; i <= n; i++) {
36+
if (!strajk[i] && vis[i] != K) {
37+
// cerr << i << " ";
38+
spojne++;
39+
bfs(i, K);
40+
}
41+
}
42+
//cerr << endl;
43+
44+
return spojne;
45+
}
46+
47+
int32_t main() {
48+
ios_base::sync_with_stdio(0);
49+
cin >> n;
50+
51+
for (int i = 1; i < n; i++) {
52+
int a, b;
53+
cin >> a >> b;
54+
assert(a < b);
55+
g[a].push_back(b);
56+
g[b].push_back(a);
57+
}
58+
59+
cin >> m;
60+
while (m--) {
61+
int v;
62+
cin >> v;
63+
if (v > 0) {
64+
assert(!strajk[v]);
65+
} else assert(strajk[-v]);
66+
67+
v = abs(v);
68+
strajk[v] = 1 - strajk[v];
69+
70+
cout << policz_spojne() << "\n";
71+
}
72+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Generatorka do zadania 'Strajki' z II etapu XXIV OI.
2+
// Autor: Paweł Putra
3+
4+
#include <bits/stdc++.h>
5+
using namespace std;
6+
int R(int a, int b) {
7+
static mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
8+
return uniform_int_distribution(a,b)(rng);
9+
}
10+
int32_t main() {
11+
ios_base::sync_with_stdio(0);
12+
int n = R(1, 10);
13+
cout << n << endl;
14+
for (int i = 2; i <= n; i++) {
15+
cout << R(1, i-1) << " " << i << "\n";
16+
}
17+
18+
int m = R(1, 10);
19+
cout << m << endl;
20+
vector<int> strajk(n+1, 0);
21+
while (m--) {
22+
int x = R(1, n);
23+
strajk[x] = 1 - strajk[x];
24+
if (strajk[x]) cout << x << "\n";
25+
else cout << -x << "\n";
26+
}
27+
}

0 commit comments

Comments
 (0)