boxin-wbx commited on
Commit
9854704
·
verified ·
1 Parent(s): d0087b7

Delete ioi2025

Browse files
ioi2025/festival.cpp DELETED
@@ -1,140 +0,0 @@
1
- #include <bits/stdc++.h>
2
- using namespace std;
3
-
4
- struct Booster {
5
- long long price; // P[i]
6
- int typ; // T[i] (2..4)
7
- int idx; // original coupon index
8
- double a; // P[i] * T[i] / (T[i]-1) for sorting
9
- };
10
-
11
- using ll = long long;
12
- const ll INF64 = numeric_limits<long long>::max();
13
-
14
- /*---------------------------------------------------------------*/
15
- /* Main function required by the statement */
16
- vector<int> max_coupons(int A,
17
- vector<int> P,
18
- vector<int> T)
19
- {
20
- const int N = (int)P.size();
21
-
22
- /* ----------- 1. split into boosters and cheap coupons ----------- */
23
- vector<Booster> boosters;
24
- boosters.reserve(N);
25
- vector<pair<ll,int>> cheap; // (price , idx)
26
- cheap.reserve(N);
27
-
28
- for (int i = 0; i < N; ++i) {
29
- if (T[i] == 1) {
30
- cheap.emplace_back(P[i], i);
31
- } else {
32
- Booster b;
33
- b.price = P[i];
34
- b.typ = T[i];
35
- b.idx = i;
36
- b.a = (double)P[i] * (double)T[i] / (double)(T[i] - 1);
37
- boosters.push_back(b);
38
- }
39
- }
40
-
41
- /* -------------------- 2. sort the two groups ------------------- */
42
- sort(boosters.begin(), boosters.end(),
43
- [](const Booster& x, const Booster& y){ return x.a < y.a; });
44
-
45
- sort(cheap.begin(), cheap.end(),
46
- [](const pair<ll,int>& x, const pair<ll,int>& y){ return x.first < y.first; });
47
-
48
- int C = (int)cheap.size();
49
- vector<ll> cheapPref(C + 1, 0); // cheapPref[0] = 0
50
- vector<int> cheapIdx(C);
51
- for (int i = 0; i < C; ++i) {
52
- cheapPref[i+1] = cheapPref[i] + cheap[i].first;
53
- cheapIdx[i] = cheap[i].second;
54
- }
55
-
56
- /* --------------------- 3. DP over boosters --------------------- */
57
- // DP vectors – state id is its position in the vectors
58
- vector<ll> tokens; // tokens left after the state
59
- vector<int> cnts; // number of boosters taken in the state
60
- vector<int> prev; // previous state id
61
- vector<int> idxs; // coupon index of the last taken booster
62
-
63
- tokens.push_back((ll)A); // state 0 – start
64
- cnts .push_back(0);
65
- prev .push_back(-1);
66
- idxs .push_back(-1);
67
-
68
- vector<int> frontier; // ids of non‑dominated states
69
- frontier.push_back(0);
70
-
71
- for (const Booster& b : boosters) {
72
- vector<int> added; // newly created states (ids)
73
- added.reserve(frontier.size());
74
-
75
- for (int sid : frontier) {
76
- if (tokens[sid] >= b.price) {
77
- // (tokens[sid] - price) * typ – do it in 128‑bit to avoid overflow
78
- __int128 tmp = (__int128)(tokens[sid] - b.price) * (ll)b.typ;
79
- ll newTok = (tmp > INF64) ? INF64 : (ll)tmp;
80
-
81
- tokens.push_back(newTok);
82
- cnts .push_back(cnts[sid] + 1);
83
- prev .push_back(sid);
84
- idxs .push_back(b.idx);
85
- added.push_back((int)tokens.size() - 1);
86
- }
87
- }
88
-
89
- // ---- merge old and new states, keep only non‑dominated ----
90
- vector<int> cand = frontier;
91
- cand.insert(cand.end(), added.begin(), added.end());
92
-
93
- sort(cand.begin(), cand.end(),
94
- [&](int a, int b) {
95
- if (tokens[a] != tokens[b]) return tokens[a] > tokens[b];
96
- return cnts[a] > cnts[b];
97
- });
98
-
99
- vector<int> newFrontier;
100
- int bestCnt = -1;
101
- for (int sid : cand) {
102
- if (cnts[sid] > bestCnt) {
103
- newFrontier.push_back(sid);
104
- bestCnt = cnts[sid];
105
- }
106
- }
107
- frontier.swap(newFrontier);
108
- }
109
-
110
- /* -------------------- 4. Choose the best final state -------------------- */
111
- long long bestTotal = -1;
112
- int bestState = -1;
113
- int bestCheap = 0; // how many cheap coupons we can buy
114
-
115
- for (int sid : frontier) {
116
- ll curTok = tokens[sid];
117
- // number of cheap coupons affordable with curTok tokens
118
- int cheapCnt = (int)(upper_bound(cheapPref.begin(), cheapPref.end(), curTok)
119
- - cheapPref.begin()) - 1;
120
- long long total = (long long)cnts[sid] + cheapCnt;
121
- if (total > bestTotal) {
122
- bestTotal = total;
123
- bestState = sid;
124
- bestCheap = cheapCnt;
125
- }
126
- }
127
-
128
- /* -------------------- 5. Reconstruct the answer -------------------- */
129
- vector<int> answer;
130
- // boosters (taken in reverse order)
131
- for (int sid = bestState; sid != 0; sid = prev[sid])
132
- answer.push_back(idxs[sid]);
133
- reverse(answer.begin(), answer.end());
134
-
135
- // cheap coupons – they are already sorted by price
136
- for (int i = 0; i < bestCheap; ++i)
137
- answer.push_back(cheapIdx[i]);
138
-
139
- return answer;
140
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ioi2025/migrations-subtask1.cpp DELETED
@@ -1,83 +0,0 @@
1
- // ------------------------------------------------------------
2
- // Dinosaur migration – research team (send_message) and Museum
3
- // ------------------------------------------------------------
4
-
5
- #include <vector>
6
- #include <utility> // std::pair
7
- #include <algorithm> // std::max
8
-
9
- // -----------------------------------------------------------------
10
- // Constants and global data that survive across calls of send_message
11
- // -----------------------------------------------------------------
12
- static const int _BLOCK = 100; // block size for the encoding
13
-
14
- // current test case size (0 means “no test case started yet”)
15
- static int _curr_N = -1;
16
-
17
- // depth[v] for the vertices that have already been visited
18
- static std::vector<int> _depth;
19
-
20
- // deepest distance seen so far and the *largest* vertex that attains it
21
- static int _max_depth = -1;
22
- static int _max_node = -1;
23
-
24
- int send_message(int N, int i, int Pi)
25
- {
26
- // (re)initialise the data structures when we get a new test case
27
- if (N != _curr_N) {
28
- _curr_N = N;
29
- _depth.assign(N, 0); // depth[0] stays 0, others are filled later
30
- _max_depth = -1;
31
- _max_node = -1;
32
- }
33
-
34
- // depth of the current vertex
35
- int d = _depth[Pi] + 1;
36
- _depth[i] = d;
37
-
38
- // keep the deepest vertex seen so far (largest index on ties)
39
- if (d > _max_depth || (d == _max_depth && i > _max_node)) {
40
- _max_depth = d;
41
- _max_node = i;
42
- }
43
-
44
- // decide what (if anything) to send from site i
45
- if (i == N - 2) { // second‑last site – send block part
46
- int block = _max_node / _BLOCK; // integer division, always >= 0
47
- return block + 1; // 1 … 100
48
- }
49
- else if (i == N - 1) { // last site – send remainder part
50
- int rem = _max_node % _BLOCK; // remainder in [0, 99]
51
- return rem + 1; // 1 … 100
52
- }
53
- else {
54
- return 0; // no message
55
- }
56
- }
57
-
58
- std::pair<int,int> longest_path(std::vector<int> S)
59
- {
60
- const int N = static_cast<int>(S.size());
61
-
62
- if (N == 1) {
63
- return {0, 0};
64
- }
65
-
66
- // The two last entries are the encoded answer.
67
- int block_val = S[N - 2];
68
- int rem_val = S[N - 1];
69
-
70
- // Convert back to the original block index (0‑based) and remainder.
71
- int block = (block_val > 0) ? (block_val - 1) : 0; // 0 … 99
72
- int rem = (rem_val > 0) ? (rem_val - 1) : 0; // 0 … 99
73
-
74
- // Re‑assemble the index of the farthest vertex.
75
- int idx = block * _BLOCK + rem;
76
-
77
- if (idx < 0) idx = 0;
78
- else if (idx >= N) idx = N - 1;
79
-
80
- // Site 0 is always an endpoint of a diameter (as required by the
81
- // original research problem). The second endpoint is `idx`.
82
- return {0, idx};
83
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ioi2025/migrations-subtask2.cpp DELETED
@@ -1,190 +0,0 @@
1
- #include <bits/stdc++.h>
2
- using namespace std;
3
-
4
- /* -----------------------------------------------------------------
5
- Global state that is shared between successive calls of
6
- send_message for the *same* test case.
7
- It is re‑initialised each time the first node (i == 1) of a new
8
- test case is processed.
9
- ----------------------------------------------------------------- */
10
- namespace {
11
- // total number of vertices of the current test case
12
- static int total_nodes = 0;
13
- // binary‑lifting depth
14
- static int LOG = 0;
15
- static vector<int> depth; // depth[v]
16
- static vector<vector<int>> up; // up[k][v] = 2^k‑th ancestor
17
-
18
- // current diameter (a,b) and its length
19
- static int a = 0, b = 0, diam = 0;
20
-
21
- // auxiliary values that are saved at specific steps
22
- static int a2 = -1; // a after node N‑2
23
- static int b2 = -1; // b after node N‑2
24
- static int b_at_N3 = -1; // b after node N‑3
25
- }
26
-
27
- /* -----------------------------------------------------------------
28
- Helper functions working on the global structures
29
- ----------------------------------------------------------------- */
30
- static void reinit(int N)
31
- {
32
- total_nodes = N;
33
- LOG = 0;
34
- while ((1 << LOG) <= N) ++LOG; // floor(log2(N)) + 1
35
- ++LOG; // a little safety margin
36
-
37
- depth.assign(N, 0); // depth[0] = 0 already
38
- up.assign(LOG, vector<int>(N, 0)); // all ancestors of the root = 0
39
-
40
- a = b = diam = 0;
41
- a2 = b2 = -1;
42
- b_at_N3 = -1;
43
- }
44
-
45
- /* LCA by binary lifting */
46
- static int lca(int u, int v)
47
- {
48
- if (depth[u] < depth[v]) swap(u, v);
49
- int diff = depth[u] - depth[v];
50
- for (int k = 0; diff; ++k) {
51
- if (diff & 1) u = up[k][u];
52
- diff >>= 1;
53
- }
54
- if (u == v) return u;
55
- for (int k = LOG - 1; k >= 0; --k) {
56
- if (up[k][u] != up[k][v]) {
57
- u = up[k][u];
58
- v = up[k][v];
59
- }
60
- }
61
- return up[0][u];
62
- }
63
-
64
- /* Distance between two vertices */
65
- static int dist(int u, int v)
66
- {
67
- int w = lca(u, v);
68
- return depth[u] + depth[v] - 2 * depth[w];
69
- }
70
-
71
- /* -----------------------------------------------------------------
72
- send_message – called while the tree is being built (sites 1 … N‑1)
73
- Returns 0 (no message) or an integer that will be sent to the museum.
74
- ----------------------------------------------------------------- */
75
- int send_message(int N, int i, int Pi) // C‑link for clarity
76
- {
77
- // first call of a new test case → initialise the global data
78
- if (i == 1) {
79
- reinit(N);
80
- }
81
-
82
- /* ---- insert the new leaf i (parent = Pi) ---- */
83
- int d = depth[Pi] + 1;
84
- depth[i] = d;
85
- up[0][i] = Pi;
86
- for (int k = 1; k < LOG; ++k) {
87
- int anc = up[k - 1][i];
88
- up[k][i] = up[k - 1][anc];
89
- }
90
-
91
- /* ---- maintain the current diameter (a,b) ---- */
92
- int da = dist(i, a);
93
- int db = dist(i, b);
94
- if (da > diam) {
95
- b = i;
96
- diam = da;
97
- } else if (db > diam) {
98
- a = i;
99
- diam = db;
100
- }
101
-
102
- /* ---- send the three tiny messages (only at i = N‑3, N‑2, N‑1) ---- */
103
- if (total_nodes >= 4 && i == total_nodes - 3 && i >= 1) {
104
- /* i == N‑3 : store b after node N‑3 (store +1 because 0 would be ambiguous) */
105
- b_at_N3 = b;
106
- return b + 1; // 1 ≤ value ≤ 20000
107
- }
108
- else if (i == total_nodes - 2 && i >= 1) {
109
- /* i == N‑2 : store a and the whole diameter after this step */
110
- a2 = a;
111
- b2 = b;
112
- return a + 1; // a+1 (still ≤ 20000)
113
- }
114
- else if (i == total_nodes - 1 && i >= 1) {
115
- /* i == N‑1 : compute the flag (1 … 5) */
116
- int a_final = a;
117
- int b_final = b;
118
- int a2_local = a2;
119
- int b2_local = b2;
120
- int b0 = b_at_N3; // b after node N‑3 (may be outdated)
121
-
122
- int flag = 1; // default (fallback)
123
-
124
- if (a_final == a2_local && b_final == b2_local) {
125
- flag = (b2_local == total_nodes - 2) ? 2 : 1;
126
- }
127
- else if (a_final == a2_local && b_final == total_nodes - 1) {
128
- flag = 3; // b replaced at the last insertion
129
- }
130
- else if (a_final == total_nodes - 1 && b_final == b2_local) {
131
- flag = (b2_local == total_nodes - 2) ? 5 : 4;
132
- }
133
- else {
134
- flag = 1; // should never happen
135
- }
136
-
137
- return flag; // already in [1,5]
138
- }
139
-
140
- return 0; // all other vertices: no message
141
- }
142
-
143
- /* -----------------------------------------------------------------
144
- longest_path – decodes the three messages produced by send_message
145
- and returns a pair of vertices that realise the tree diameter.
146
- ----------------------------------------------------------------- */
147
- pair<int,int> longest_path(vector<int> S)
148
- {
149
- size_t N = S.size();
150
-
151
- if (N <= 1) return {0, 0};
152
- if (N == 2) return {0, 1};
153
- if (N == 3) return {1, 2};
154
-
155
- // N >= 4 : three stored values are at positions N‑3, N‑2, N‑1
156
- int a_msg = S[N - 2]; // a after node N‑2 (+1)
157
- int b_msg = S[N - 3]; // b after node N‑3 (+1)
158
- int flag = S[N - 1]; // 1 … 5
159
-
160
- int a = a_msg - 1; // a after node N‑2
161
- int b0 = b_msg - 1; // b after node N‑3
162
-
163
- int u, v;
164
- switch (flag) {
165
- case 1: // both old endpoints survive
166
- u = a;
167
- v = b0;
168
- break;
169
- case 2: // b changed at N‑2, a survived
170
- u = a;
171
- v = static_cast<int>(N) - 2;
172
- break;
173
- case 3: // b replaced at N‑1, a survived
174
- u = a;
175
- v = static_cast<int>(N) - 1;
176
- break;
177
- case 4: // a replaced at N‑1, b survived (b unchanged at N‑2)
178
- u = b0;
179
- v = static_cast<int>(N) - 1;
180
- break;
181
- case 5: // a replaced at N‑1, b changed at N‑2
182
- u = static_cast<int>(N) - 2;
183
- v = static_cast<int>(N) - 1;
184
- break;
185
- default: // safety fallback – should never be hit
186
- u = a;
187
- v = b0;
188
- }
189
- return {u, v};
190
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ioi2025/obstacles.cpp DELETED
@@ -1,222 +0,0 @@
1
- #include <bits/stdc++.h>
2
- using namespace std;
3
-
4
- /* ------------------------------------------------------------------ */
5
- /* Disjoint Set Union (Union–Find) */
6
- /* ------------------------------------------------------------------ */
7
- struct DSU {
8
- vector<int> parent, sz;
9
- DSU(int n = 0) { init(n); }
10
-
11
- void init(int n) {
12
- parent.resize(n);
13
- sz.assign(n, 1);
14
- iota(parent.begin(), parent.end(), 0);
15
- }
16
-
17
- int find(int x) {
18
- while (parent[x] != x) {
19
- parent[x] = parent[parent[x]];
20
- x = parent[x];
21
- }
22
- return x;
23
- }
24
-
25
- void union_sets(int a, int b) {
26
- a = find(a);
27
- b = find(b);
28
- if (a == b) return;
29
- if (sz[a] < sz[b]) swap(a, b);
30
- parent[b] = a;
31
- sz[a] += sz[b];
32
- }
33
- };
34
-
35
- /* ------------------------------------------------------------------ */
36
- /* Segment tree for range maximum (static) */
37
- /* ------------------------------------------------------------------ */
38
- struct MaxSegTree {
39
- int n; // original size
40
- int size; // power of two >= n
41
- vector<int> tree; // 2*size elements
42
-
43
- MaxSegTree() : n(0), size(0) {}
44
-
45
- explicit MaxSegTree(const vector<int>& data) {
46
- build(data);
47
- }
48
-
49
- void build(const vector<int>& data) {
50
- n = static_cast<int>(data.size());
51
- size = 1;
52
- while (size < n) size <<= 1;
53
- tree.assign(2 * size, 0);
54
- for (int i = 0; i < n; ++i) tree[size + i] = data[i];
55
- for (int i = size - 1; i > 0; --i)
56
- tree[i] = max(tree[i << 1], tree[i << 1 | 1]);
57
- }
58
-
59
- // inclusive query [l, r]; returns -1 for empty interval
60
- int query(int l, int r) const {
61
- if (l > r) return -1;
62
- l += size; r += size;
63
- int res = -1;
64
- while (l <= r) {
65
- if (l & 1) res = max(res, tree[l++]);
66
- if (!(r & 1)) res = max(res, tree[r--]);
67
- l >>= 1; r >>= 1;
68
- }
69
- return res;
70
- }
71
- };
72
-
73
- /* ------------------------------------------------------------------ */
74
- /* Segment tree that stores min / max *active* column indices */
75
- /* ------------------------------------------------------------------ */
76
- struct ActiveSegTree {
77
- int n; // number of columns
78
- int size; // power of two >= n
79
- vector<int> max_tree; // maximum active index inside the node
80
- vector<int> min_tree; // minimum active index inside the node
81
-
82
- explicit ActiveSegTree(int n_) : n(n_) {
83
- size = 1;
84
- while (size < n) size <<= 1;
85
- max_tree.assign(2 * size, -1);
86
- min_tree.assign(2 * size, n);
87
- }
88
-
89
- // mark column idx as active
90
- void activate(int idx) {
91
- int i = idx + size;
92
- max_tree[i] = idx;
93
- min_tree[i] = idx;
94
- for (i >>= 1; i; i >>= 1) {
95
- int left = i << 1;
96
- int right = left | 1;
97
- max_tree[i] = max(max_tree[left], max_tree[right]);
98
- min_tree[i] = min(min_tree[left], min_tree[right]);
99
- }
100
- }
101
-
102
- // maximum active index in [l, r]; -1 if none
103
- int query_max(int l, int r) const {
104
- if (l > r) return -1;
105
- l += size; r += size;
106
- int res = -1;
107
- while (l <= r) {
108
- if (l & 1) res = max(res, max_tree[l++]);
109
- if (!(r & 1)) res = max(res, max_tree[r--]);
110
- l >>= 1; r >>= 1;
111
- }
112
- return res;
113
- }
114
-
115
- // minimum active index in [l, r]; n if none
116
- int query_min(int l, int r) const {
117
- if (l > r) return n;
118
- l += size; r += size;
119
- int res = n;
120
- while (l <= r) {
121
- if (l & 1) res = min(res, min_tree[l++]);
122
- if (!(r & 1)) res = min(res, min_tree[r--]);
123
- l >>= 1; r >>= 1;
124
- }
125
- return res;
126
- }
127
- };
128
-
129
- int N = 0, M = 0;
130
- vector<int> pref_max; // prefix maximum of T, length N
131
- vector<int> comp; // component id for each column
132
- DSU* dsu = nullptr; // created inside initialize
133
-
134
- /* ------------------------------------------------------------------ */
135
- /* Interface required by the statement */
136
- /* ------------------------------------------------------------------ */
137
- void initialize(vector<int> T, vector<int> H)
138
- {
139
- N = static_cast<int>(T.size());
140
- M = static_cast<int>(H.size());
141
-
142
- /* 1. prefix maximum of temperatures */
143
- pref_max.assign(N, 0);
144
- pref_max[0] = T[0];
145
- for (int i = 1; i < N; ++i)
146
- pref_max[i] = max(pref_max[i-1], T[i]);
147
-
148
- /* 2. first blocked row for every column */
149
- vector<int> col_by_h(M);
150
- iota(col_by_h.begin(), col_by_h.end(), 0);
151
- sort(col_by_h.begin(), col_by_h.end(),
152
- [&](int a, int b){ return H[a] > H[b]; });
153
-
154
- vector<int> first_block(M, N);
155
- int ptr = 0;
156
- for (int i = 0; i < N; ++i) {
157
- int ti = T[i];
158
- while (ptr < M && H[col_by_h[ptr]] >= ti) {
159
- int col = col_by_h[ptr];
160
- first_block[col] = i;
161
- ++ptr;
162
- }
163
- }
164
-
165
- vector<int> Lcol(M);
166
- for (int j = 0; j < M; ++j) {
167
- if (first_block[j] == N) Lcol[j] = N - 1;
168
- else Lcol[j] = first_block[j] - 1;
169
- }
170
-
171
- /* 3. V[j] = max temperature in rows 0 … Lcol[j] */
172
- vector<int> V(M);
173
- for (int j = 0; j < M; ++j) {
174
- if (Lcol[j] >= 0) V[j] = pref_max[Lcol[j]];
175
- else V[j] = -1; // column can never be reached
176
- }
177
-
178
- /* 4. segment tree for range maximum of humidity (static) */
179
- MaxSegTree seg_H(H);
180
-
181
- /* 5. DSU over columns */
182
- dsu = new DSU(M);
183
-
184
- /* 6. process columns in decreasing V */
185
- vector<int> order(M);
186
- iota(order.begin(), order.end(), 0);
187
- sort(order.begin(), order.end(),
188
- [&](int a, int b){ return V[a] > V[b]; });
189
-
190
- ActiveSegTree active_seg(M); // no column active at the beginning
191
-
192
- for (int col : order) {
193
- int vcol = V[col];
194
- active_seg.activate(col); // make the column active
195
-
196
- // ---- left neighbour ----
197
- int left = -1;
198
- if (col > 0) left = active_seg.query_max(0, col - 1);
199
- if (left != -1) {
200
- int max_h = seg_H.query(left, col);
201
- if (max_h < vcol) dsu->union_sets(col, left);
202
- }
203
-
204
- // ---- right neighbour ----
205
- int right = M;
206
- if (col + 1 < M) right = active_seg.query_min(col + 1, M - 1);
207
- if (right != M) {
208
- int max_h = seg_H.query(col, right);
209
- if (max_h < vcol) dsu->union_sets(col, right);
210
- }
211
- }
212
-
213
- /* 7. store the component id for every column */
214
- comp.resize(M);
215
- for (int i = 0; i < M; ++i) comp[i] = dsu->find(i);
216
- }
217
-
218
- bool can_reach(int L, int R, int S, int D)
219
- {
220
- (void)L; (void)R; // unused, required by the signature
221
- return comp[S] == comp[D];
222
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ioi2025/souvenirs-subtask1_3.cpp DELETED
@@ -1,46 +0,0 @@
1
- #include <vector>
2
- #include <utility>
3
-
4
- using namespace std;
5
-
6
- // Provided by the judge. It returns the list of types bought and the
7
- // number of coins that remain after giving M coins.
8
- pair<vector<int>, long long> transaction(long long M);
9
-
10
- void buy_souvenirs(int N, long long P0)
11
- {
12
- vector<long long> price(N, 0);
13
- vector<int> bought(N, 0);
14
-
15
- price[0] = P0; // price of type 0 is known
16
-
17
- // -------- Phase 1 : discover all prices ----------
18
- for (int i = 1; i < N; ++i) {
19
- long long M = price[i - 1] - 1; // guaranteed < price[i-1] and ≥ price[i]
20
- auto [L, R] = transaction(M); // L – bought types, R – remaining coins
21
-
22
- for (int t : L) ++bought[t];
23
-
24
- long long spent = M - R; // total money spent in this transaction
25
-
26
- if (L.size() == 1) {
27
- price[i] = spent; // only type i was bought
28
- } else {
29
- price[i] = spent - 1; // cheapest type (price 1) was also bought
30
- int extra = -1;
31
- for (int t : L) if (t != i) { extra = t; break; }
32
- if (extra != -1 && price[extra] == 0) {
33
- price[extra] = 1; // cheapest type has price 1
34
- }
35
- }
36
- }
37
-
38
- // -------- Phase 2 : buy the remaining copies ----------
39
- for (int i = 1; i < N; ++i) {
40
- while (bought[i] < i) {
41
- long long M = price[i]; // give exactly the price of type i
42
- auto [L, R] = transaction(M);
43
- for (int t : L) ++bought[t];
44
- }
45
- }
46
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ioi2025/souvenirs-subtask4.cpp DELETED
@@ -1,22 +0,0 @@
1
- #include <vector>
2
- #include <utility>
3
-
4
- std::pair<std::vector<int>, long long> transaction(long long M); // provided by the judge
5
-
6
- void buy_souvenirs(int N, long long P0)
7
- {
8
- long long M1 = P0 - 1;
9
- auto [L1, R1] = transaction(M1);
10
-
11
- if (L1.size() == 2) {
12
- long long S = M1 - R1;
13
- long long M2 = S / 2;
14
- transaction(M2);
15
- return;
16
- }
17
-
18
- long long P1 = M1 - R1;
19
- long long M = P1 - 1;
20
- transaction(M);
21
- transaction(M);
22
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ioi2025/triples-part1.cpp DELETED
@@ -1,126 +0,0 @@
1
- #include <bits/stdc++.h>
2
- using namespace std;
3
-
4
- long long count_triples(vector<int> H)
5
- {
6
- const int N = static_cast<int>(H.size());
7
-
8
- long long cnt1 = 0, cnt2 = 0, cnt3 = 0, cnt4 = 0,
9
- cnt5 = 0, cnt6 = 0, equal_cnt = 0;
10
-
11
- /* ---------- assignment 1 ---------- */
12
- for (int i = 0; i < N; ++i) {
13
- int j = i + H[i];
14
- if (j >= N) continue;
15
- int b = H[j];
16
- int k = j + b;
17
- if (k >= N) continue;
18
- if (H[k] == H[i] + b) ++cnt1;
19
- }
20
-
21
- /* ---------- assignment 2 ---------- */
22
- for (int i = 0; i < N; ++i) {
23
- int j = i + H[i];
24
- if (j >= N) continue;
25
- int b = H[j] - H[i];
26
- if (b <= 0) continue;
27
- int k = j + b;
28
- if (k >= N) continue;
29
- if (H[k] == b) ++cnt2;
30
- }
31
-
32
- /* ---------- assignment 3 ---------- */
33
- for (int j = 0; j < N; ++j) {
34
- int i = j - H[j];
35
- if (i < 0) continue;
36
- int b = H[i];
37
- int k = j + b;
38
- if (k >= N) continue;
39
- if (H[k] == H[j] + b) ++cnt3;
40
- }
41
-
42
- /* ---------- assignment 5 ---------- */
43
- for (int j = 0; j < N; ++j) {
44
- int i = j - H[j];
45
- if (i < 0) continue;
46
- int b = H[i] - H[j];
47
- if (b <= 0) continue;
48
- int k = j + b;
49
- if (k >= N) continue;
50
- if (H[k] == b) ++cnt5;
51
- }
52
-
53
- /* ---------- assignment 6 ---------- */
54
- for (int j = 0; j < N; ++j) {
55
- int k = j + H[j];
56
- if (k >= N) continue;
57
- int a = H[k];
58
- int i = j - a;
59
- if (i < 0) continue;
60
- if (H[i] == a + H[j]) ++cnt6;
61
- }
62
-
63
- /* ---------- assignment 4 (group i+H[i] = k-H[k]) ---------- */
64
- // groups[T] = list of k such that k - H[k] == T (T = “key”)
65
- unordered_map<int, vector<int>> groups;
66
- groups.reserve(N * 2);
67
- for (int k = 0; k < N; ++k) {
68
- int T = k - H[k];
69
- groups[T].push_back(k); // k grows, so each vector stays sorted
70
- }
71
-
72
- for (int i = 0; i < N; ++i) {
73
- int T = i + H[i];
74
- auto it = groups.find(T);
75
- if (it == groups.end()) continue; // no k with the needed key
76
-
77
- const vector<int>& ks = it->second;
78
- // first k that is > i
79
- auto posIter = upper_bound(ks.begin(), ks.end(), i);
80
- int H_i = H[i];
81
-
82
- for (auto kIt = posIter; kIt != ks.end(); ++kIt) {
83
- int k = *kIt;
84
- int j = k - H_i;
85
- if (j >= N) break; // larger k → larger j, so we can stop
86
- // i < j < k holds automatically for the chosen ks
87
- if (H[j] == k - i) ++cnt4;
88
- }
89
- }
90
-
91
- long long total = cnt1 + cnt2 + cnt3 + cnt4 + cnt5 + cnt6;
92
-
93
- /* ---------- triples with equal distances (a = b) ----------
94
- These triples were counted twice (once in the main total and
95
- once in the equal‑distance special case), therefore we subtract
96
- them once at the end. */
97
- for (int i = 0; i < N; ++i) {
98
- int a = H[i];
99
-
100
- // case 1 : distance = a (i → j → k, with j = i+a, k = i+2a)
101
- int j = i + a;
102
- if (j < N) {
103
- int k = i + 2 * a;
104
- if (k < N) {
105
- bool ok = (H[j] == a && H[k] == 2 * a) ||
106
- (H[j] == 2 * a && H[k] == a);
107
- if (ok) ++equal_cnt;
108
- }
109
- }
110
-
111
- // case 2 : distance = 2a (i → j (a) → k (2a), but we treat a = H[i]/2)
112
- if (a % 2 == 0) {
113
- int a2 = a / 2;
114
- if (a2 > 0) {
115
- j = i + a2;
116
- int k = i + a; // i + 2*a2 = i + a
117
- if (j < N && k < N) {
118
- if (H[j] == a2 && H[k] == a2) ++equal_cnt;
119
- }
120
- }
121
- }
122
- }
123
-
124
- return total - equal_cnt;
125
- }
126
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ioi2025/triples-part2-subtask1.cpp DELETED
@@ -1,141 +0,0 @@
1
- #include <algorithm>
2
- #include <array>
3
- #include <cassert>
4
- #include <random>
5
- #include <vector>
6
-
7
- /* ----------------------------------------------------------------------
8
- Helper type – a triple together with the *sorted* list of its three
9
- distances (d1 , d2 , d3). The distances are stored already sorted so
10
- we can compare them directly with the sorted heights of the same
11
- triple.
12
- ---------------------------------------------------------------------- */
13
- struct Triple
14
- {
15
- int i{}, j{}, k{}; // indices i<j<k
16
- std::array<int, 3> ds{}; // sorted distances (d1,d2,d3)
17
-
18
- Triple(int a, int b, int c) : i(a), j(b), k(c)
19
- {
20
- int d1 = j - i;
21
- int d2 = k - j;
22
- int d3 = k - i;
23
- ds = { d1, d2, d3 };
24
- std::sort(ds.begin(), ds.end()); // make it sorted (ds[0] ≤ ds[1] ≤ ds[2])
25
- }
26
- };
27
-
28
- /* ----------------------------------------------------------------------
29
- Count how many triples are *mythical* for a given height vector H.
30
- A triple is mythical iff the three heights (sorted) are exactly the
31
- three distances (also sorted) of that triple.
32
- ---------------------------------------------------------------------- */
33
- static int countTriples(const std::vector<int>& H,
34
- const std::vector<Triple>& triples)
35
- {
36
- int cnt = 0;
37
- for (const auto& tr : triples)
38
- {
39
- std::array<int,3> hs = { H[tr.i], H[tr.j], H[tr.k] };
40
- std::sort(hs.begin(), hs.end());
41
-
42
- if (hs == tr.ds) ++cnt;
43
- }
44
- return cnt;
45
- }
46
-
47
- std::vector<int> construct_range(int M, int K)
48
- {
49
- /* ---- 1. pre‑compute all triples for N = max(3,M) ----------------- */
50
- const int N = std::max(3, M);
51
- std::vector<Triple> triples;
52
- triples.reserve(N * (N-1) * (N-2) / 6); // upper bound for #triples
53
-
54
- for (int i = 0; i < N; ++i)
55
- for (int j = i + 1; j < N; ++j)
56
- for (int k = j + 1; k < N; ++k)
57
- triples.emplace_back(i, j, k);
58
-
59
- /* ---- 2. random search ------------------------------------------------ */
60
- std::mt19937 rng{ std::random_device{}() };
61
-
62
- // distribution for the initial random heights: 1 … N‑1 (inclusive)
63
- std::uniform_int_distribution<int> initDist(1, N - 1);
64
-
65
- // same distribution we will use when we need a random element of `ds`
66
- // (the distances themselves are already in the range 1 … N‑1)
67
- // No extra work required – we simply shuffle the three already‑present
68
- // numbers.
69
-
70
- int best_cnt = -1;
71
- std::vector<int> best_H;
72
-
73
- const int max_restarts = 5;
74
- const int max_moves = 20000; // moves per restart
75
-
76
- for (int restart = 0; restart < max_restarts; ++restart)
77
- {
78
- /* ---- a) random initial configuration --------------------------- */
79
- std::vector<int> cur_H(N);
80
- for (int i = 0; i < N; ++i)
81
- cur_H[i] = initDist(rng);
82
-
83
- int cur_cnt = countTriples(cur_H, triples);
84
-
85
- if (cur_cnt > best_cnt)
86
- {
87
- best_cnt = cur_cnt;
88
- best_H = cur_H;
89
- }
90
- if (cur_cnt >= K)
91
- return cur_H; // we already hit the target
92
-
93
- /* ---- b) local hill‑climbing / random‑move phase ----------------- */
94
- std::vector<int> cur = cur_H; // we will mutate this copy
95
-
96
- for (int move = 0; move < max_moves; ++move)
97
- {
98
- // pick a random triple
99
- const Triple& tr = triples[ std::uniform_int_distribution<int>(0, triples.size() - 1)(rng) ];
100
-
101
- // remember the old three heights (so we can revert)
102
- int old_i = cur[tr.i];
103
- int old_j = cur[tr.j];
104
- int old_k = cur[tr.k];
105
-
106
- // permute the three distances of this triple
107
- std::array<int,3> dlist = tr.ds; // copy
108
- std::shuffle(dlist.begin(), dlist.end(), rng);
109
-
110
- // apply the move
111
- cur[tr.i] = dlist[0];
112
- cur[tr.j] = dlist[1];
113
- cur[tr.k] = dlist[2];
114
-
115
- int new_cnt = countTriples(cur, triples);
116
-
117
- // accept the move only if it does not make the global count worse
118
- if (new_cnt >= cur_cnt)
119
- {
120
- cur_cnt = new_cnt;
121
- if (cur_cnt > best_cnt)
122
- {
123
- best_cnt = cur_cnt;
124
- best_H = cur;
125
- }
126
- if (cur_cnt >= K)
127
- return cur; // success – we reached K
128
- }
129
- else
130
- {
131
- // revert the move (the triple must be mythical again)
132
- cur[tr.i] = old_i;
133
- cur[tr.j] = old_j;
134
- cur[tr.k] = old_k;
135
- }
136
- } // end of one restart's move loop
137
- } // end of all restarts
138
-
139
- // never reached K – return the best we ever found (it is still a legal vector)
140
- return best_H;
141
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ioi2025/triples-part2-subtask2.cpp DELETED
@@ -1,358 +0,0 @@
1
- #include <bits/stdc++.h>
2
-
3
- using namespace std;
4
-
5
- long long count_triples(vector<int> H)
6
- {
7
- const int N = static_cast<int>(H.size());
8
-
9
- long long cnt1 = 0, cnt2 = 0, cnt3 = 0, cnt4 = 0,
10
- cnt5 = 0, cnt6 = 0, equal_cnt = 0;
11
-
12
- /* ---------- assignment 1 ---------- */
13
- for (int i = 0; i < N; ++i) {
14
- int j = i + H[i];
15
- if (j >= N) continue;
16
- int b = H[j];
17
- int k = j + b;
18
- if (k >= N) continue;
19
- if (H[k] == H[i] + b) ++cnt1;
20
- }
21
-
22
- /* ---------- assignment 2 ---------- */
23
- for (int i = 0; i < N; ++i) {
24
- int j = i + H[i];
25
- if (j >= N) continue;
26
- int b = H[j] - H[i];
27
- if (b <= 0) continue;
28
- int k = j + b;
29
- if (k >= N) continue;
30
- if (H[k] == b) ++cnt2;
31
- }
32
-
33
- /* ---------- assignment 3 ---------- */
34
- for (int j = 0; j < N; ++j) {
35
- int i = j - H[j];
36
- if (i < 0) continue;
37
- int b = H[i];
38
- int k = j + b;
39
- if (k >= N) continue;
40
- if (H[k] == H[j] + b) ++cnt3;
41
- }
42
-
43
- /* ---------- assignment 5 ---------- */
44
- for (int j = 0; j < N; ++j) {
45
- int i = j - H[j];
46
- if (i < 0) continue;
47
- int b = H[i] - H[j];
48
- if (b <= 0) continue;
49
- int k = j + b;
50
- if (k >= N) continue;
51
- if (H[k] == b) ++cnt5;
52
- }
53
-
54
- /* ---------- assignment 6 ---------- */
55
- for (int j = 0; j < N; ++j) {
56
- int k = j + H[j];
57
- if (k >= N) continue;
58
- int a = H[k];
59
- int i = j - a;
60
- if (i < 0) continue;
61
- if (H[i] == a + H[j]) ++cnt6;
62
- }
63
-
64
- /* ---------- assignment 4 (group i+H[i] = k-H[k]) ---------- */
65
- // groups[T] = list of k such that k - H[k] == T (T = “key”)
66
- unordered_map<int, vector<int>> groups;
67
- groups.reserve(N * 2);
68
- for (int k = 0; k < N; ++k) {
69
- int T = k - H[k];
70
- groups[T].push_back(k); // k grows, so each vector stays sorted
71
- }
72
-
73
- for (int i = 0; i < N; ++i) {
74
- int T = i + H[i];
75
- auto it = groups.find(T);
76
- if (it == groups.end()) continue; // no k with the needed key
77
-
78
- const vector<int>& ks = it->second;
79
- // first k that is > i
80
- auto posIter = upper_bound(ks.begin(), ks.end(), i);
81
- int H_i = H[i];
82
-
83
- for (auto kIt = posIter; kIt != ks.end(); ++kIt) {
84
- int k = *kIt;
85
- int j = k - H_i;
86
- if (j >= N) break; // larger k → larger j, so we can stop
87
- // i < j < k holds automatically for the chosen ks
88
- if (H[j] == k - i) ++cnt4;
89
- }
90
- }
91
-
92
- long long total = cnt1 + cnt2 + cnt3 + cnt4 + cnt5 + cnt6;
93
-
94
- /* ---------- triples with equal distances (a = b) ----------
95
- These triples were counted twice (once in the main total and
96
- once in the equal‑distance special case), therefore we subtract
97
- them once at the end. */
98
- for (int i = 0; i < N; ++i) {
99
- int a = H[i];
100
-
101
- // case 1 : distance = a (i → j → k, with j = i+a, k = i+2a)
102
- int j = i + a;
103
- if (j < N) {
104
- int k = i + 2 * a;
105
- if (k < N) {
106
- bool ok = (H[j] == a && H[k] == 2 * a) ||
107
- (H[j] == 2 * a && H[k] == a);
108
- if (ok) ++equal_cnt;
109
- }
110
- }
111
-
112
- // case 2 : distance = 2a (i → j (a) → k (2a), but we treat a = H[i]/2)
113
- if (a % 2 == 0) {
114
- int a2 = a / 2;
115
- if (a2 > 0) {
116
- j = i + a2;
117
- int k = i + a; // i + 2*a2 = i + a
118
- if (j < N && k < N) {
119
- if (H[j] == a2 && H[k] == a2) ++equal_cnt;
120
- }
121
- }
122
- }
123
- }
124
-
125
- return total - equal_cnt;
126
- }
127
-
128
-
129
-
130
- /* -------------------------------------------------------------
131
- 2. greedy_builder – builds a candidate array from (h0,h1)
132
- ------------------------------------------------------------- */
133
- static vector<int> greedy_builder(int N, int h0, int h1,
134
- int D, int max_h)
135
- {
136
- vector<int> H(N, 1);
137
- H[0] = h0;
138
- H[1] = h1;
139
-
140
- vector<int> cnt(max_h + 1, 0);
141
- vector<int> last(max_h + 1, 0);
142
- int version = 0;
143
- const int twoD = 2 * D;
144
-
145
- for (int k = 2; k < N; ++k) {
146
- ++version;
147
- int best_cnt = 0;
148
- int best_missing = 1;
149
- int i_start = k - twoD;
150
- if (i_start < 0) i_start = 0;
151
-
152
- for (int i = i_start; i < k; ++i) {
153
- int hi = H[i];
154
- int s = k - i;
155
- if (hi >= s) continue;
156
-
157
- // ----- left candidate j = i + hi -----
158
- int j = i + hi;
159
- if (j < k) {
160
- int a = hi;
161
- int b = s - hi;
162
- int hj = H[j];
163
- bool ok = (hj == a || hj == b || hj == s) &&
164
- !(a != b && hi == hj);
165
- if (ok) {
166
- int missing = 2 * s - hi - hj;
167
- if (1 <= missing && missing <= max_h) {
168
- if (last[missing] != version) {
169
- cnt[missing] = 1;
170
- last[missing] = version;
171
- } else {
172
- ++cnt[missing];
173
- }
174
- if (cnt[missing] > best_cnt) {
175
- best_cnt = cnt[missing];
176
- best_missing = missing;
177
- }
178
- }
179
- }
180
- }
181
-
182
- // ----- right candidate j2 = k - hi -----
183
- int j2 = k - hi;
184
- if (j2 > i && j2 != i + hi) {
185
- int a = s - hi;
186
- int b = hi;
187
- int hj = H[j2];
188
- bool ok = (hj == a || hj == b || hj == s) &&
189
- !(a != b && hi == hj);
190
- if (ok) {
191
- int missing = 2 * s - hi - hj;
192
- if (1 <= missing && missing <= max_h) {
193
- if (last[missing] != version) {
194
- cnt[missing] = 1;
195
- last[missing] = version;
196
- } else {
197
- ++cnt[missing];
198
- }
199
- if (cnt[missing] > best_cnt) {
200
- best_cnt = cnt[missing];
201
- best_missing = missing;
202
- }
203
- }
204
- }
205
- }
206
- }
207
-
208
- H[k] = (best_cnt > 0) ? best_missing : 1;
209
- }
210
- return H;
211
- }
212
-
213
- /* -------------------------------------------------------------
214
- 3. construct_range – the whole construction routine
215
- ------------------------------------------------------------- */
216
- vector<int> construct_range(int M, int K)
217
- {
218
- const int N = max(3, M); // we always use exactly N = M (M>=3 in tests)
219
- const int max_h = N - 1;
220
- int D = (N - 1) / 2;
221
- if (D == 0) D = 1;
222
-
223
- long long best_T = -1;
224
- vector<int> best_H;
225
-
226
- /* ----- helper: evaluate a candidate and keep the best one ----- */
227
- auto evaluate = [&](const vector<int>& H) {
228
- long long T = count_triples(H);
229
- if (T > best_T) {
230
- best_T = T;
231
- best_H = H;
232
- if (best_T >= K) throw runtime_error("enough triples");
233
- }
234
- };
235
-
236
- /* ----- deterministic patterns ----- */
237
- auto add_pattern = [&](const vector<int>& pat) {
238
- int repeats = N / static_cast<int>(pat.size()) + 1;
239
- vector<int> H;
240
- H.reserve(N);
241
- for (int i = 0; i < repeats; ++i) H.insert(H.end(), pat.begin(), pat.end());
242
- H.resize(N);
243
- evaluate(H);
244
- };
245
-
246
- add_pattern({1, 1, 2});
247
- add_pattern({1, 2, 1});
248
- add_pattern({2, 1, 1});
249
-
250
- // a2 pattern – 4 on positions whose block‑index %3 ==0
251
- vector<int> H(N);
252
- for (int i = 0; i < N; ++i) {
253
- if (i % 2 == 0) { // even index
254
- int pos = i / 2;
255
- H[i] = (pos % 3 == 0) ? 4 : 2;
256
- } else { // odd index
257
- int pos = (i - 1) / 2;
258
- H[i] = (pos % 3 == 0) ? 4 : 2;
259
- }
260
- }
261
- evaluate(H);
262
-
263
- /* ----- start pairs for the greedy builder ----- */
264
- unordered_set<long long> start_pairs; // encode pair (h0,h1) in a 64‑bit key
265
- auto encode = [&](int a, int b) -> long long { return (static_cast<long long>(a) << 32) | static_cast<unsigned int>(b); };
266
-
267
- int limit = min(20, max_h);
268
- for (int h0 = 1; h0 <= limit; ++h0)
269
- for (int h1 = 1; h1 <= limit; ++h1)
270
- start_pairs.insert(encode(h0, h1));
271
-
272
- start_pairs.insert(encode(max_h, max_h));
273
- start_pairs.insert(encode(max_h, 1));
274
- start_pairs.insert(encode(1, max_h));
275
- if (max_h >= 2) {
276
- start_pairs.insert(encode(max_h - 1, max_h - 1));
277
- start_pairs.insert(encode(max_h - 2, max_h - 2));
278
- }
279
-
280
- mt19937_64 rnd(123456789ULL);
281
- for (int i = 0; i < 30; ++i) {
282
- int h0 = uniform_int_distribution<int>(1, max_h)(rnd);
283
- int h1 = uniform_int_distribution<int>(1, max_h)(rnd);
284
- start_pairs.insert(encode(h0, h1));
285
- }
286
-
287
- vector<pair<int,int>> start_list;
288
- start_list.reserve(start_pairs.size());
289
- for (auto key : start_pairs) {
290
- int h0 = static_cast<int>(key >> 32);
291
- int h1 = static_cast<int>(key & 0xffffffff);
292
- start_list.emplace_back(h0, h1);
293
- }
294
- shuffle(start_list.begin(), start_list.end(),
295
- mt19937_64(987654321ULL));
296
-
297
- /* ----- greedy builder for every start pair ----- */
298
- try {
299
- for (auto [h0, h1] : start_list) {
300
- int h0c = max(1, min(max_h, h0));
301
- int h1c = max(1, min(max_h, h1));
302
- vector<int> cand = greedy_builder(N, h0c, h1c, D, max_h);
303
- evaluate(cand);
304
- }
305
- } catch (const runtime_error&) {
306
- // we already hit K – just keep the current best
307
- }
308
-
309
- /* ----- hill climbing if needed ----- */
310
- if (best_T < K) {
311
- vector<int> cur_H = best_H;
312
- long long cur_T = best_T;
313
-
314
- // values we are allowed to change to (small numbers + the maximal one)
315
- vector<int> cand_vals;
316
- int small_limit = min(N, 30);
317
- for (int v = 1; v <= small_limit; ++v) cand_vals.push_back(v);
318
- if (max_h > small_limit) cand_vals.push_back(max_h);
319
- sort(cand_vals.begin(), cand_vals.end());
320
- cand_vals.erase(unique(cand_vals.begin(), cand_vals.end()), cand_vals.end());
321
-
322
- mt19937_64 rnd_hc(987654321ULL);
323
- uniform_int_distribution<int> idx_dist(0, N - 1);
324
- uniform_int_distribution<int> val_dist(0, static_cast<int>(cand_vals.size()) - 1);
325
-
326
- for (int step = 0; step < 20000 && best_T < K; ++step) {
327
- int i = idx_dist(rnd_hc);
328
- int new_val = cand_vals[val_dist(rnd_hc)];
329
- if (new_val == cur_H[i]) continue;
330
-
331
- int old = cur_H[i];
332
- cur_H[i] = new_val;
333
- long long new_T = count_triples(cur_H);
334
- if (new_T > cur_T) {
335
- cur_T = new_T;
336
- if (new_T > best_T) {
337
- best_T = new_T;
338
- best_H = cur_H;
339
- if (best_T >= K) break;
340
- }
341
- } else {
342
- cur_H[i] = old; // revert
343
- }
344
- }
345
- }
346
-
347
- /* ----- final safety clamp ----- */
348
- vector<int> out_H(N);
349
- for (int i = 0; i < N; ++i) {
350
- int v = best_H[i];
351
- if (v < 1) v = 1;
352
- if (v > max_h) v = max_h;
353
- out_H[i] = v;
354
- }
355
- out_H.resize(N);
356
- return out_H;
357
- }
358
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ioi2025/triples-part2-subtask3.cpp DELETED
@@ -1,196 +0,0 @@
1
- #include <algorithm>
2
- #include <cassert>
3
- #include <random>
4
- #include <utility>
5
- #include <vector>
6
- #include <cstdint>
7
- #include <unordered_map>
8
-
9
- /* ------------------------------------------------------------------ */
10
- /* Helper that implements the “greedy builder”. */
11
- /* It returns both the constructed height vector H and the total T. */
12
- /* ------------------------------------------------------------------ */
13
- static std::pair<std::vector<int>, long long>
14
- greedy_builder(int N,
15
- int h0,
16
- int h1,
17
- const std::vector<int>& useful_vals,
18
- std::mt19937& rng)
19
- {
20
- std::vector<int> H(N, 0);
21
- H[0] = h0;
22
- H[1] = h1;
23
-
24
- const int max_missing = N - 1; // allowed values are 1 … max_missing
25
- std::vector<int> cnt(max_missing + 1, 0);
26
- std::vector<int> last(max_missing + 1, 0);
27
-
28
- long long total_T = 0; // may be larger than int
29
- const int D = (N - 1) / 2;
30
- const int twoD = 2 * D;
31
-
32
- int version = 0; // increased for every k
33
-
34
- for (int k = 2; k < N; ++k) {
35
- ++version; // new “run” for this k
36
-
37
- int best_cnt = 0; // best counter for this k
38
- int best_missing = 1; // associated missing value
39
-
40
- int i_start = k - twoD;
41
- if (i_start < 0) i_start = 0;
42
-
43
- for (int i = i_start; i < k; ++i) {
44
- int hi = H[i];
45
- int s = k - i; // s = k-i > 0
46
-
47
- if (hi >= s) continue; // no candidate possible
48
-
49
- /* ---------- left distance candidate j = i + hi ---------- */
50
- int j = i + hi;
51
- if (j < k) {
52
- int a = hi;
53
- int b = s - hi; // the two distances that must appear together
54
- int hj = H[j];
55
- if (hj == a || hj == b || hj == s) {
56
- if (! (a != b && hi == hj)) { // the “not (a!=b && hi==hj)” guard
57
- int missing = 2 * s - hi - hj;
58
- if (1 <= missing && missing <= max_missing) {
59
- if (last[missing] != version) {
60
- cnt[missing] = 1;
61
- last[missing] = version;
62
- } else {
63
- ++cnt[missing];
64
- }
65
- int cur = cnt[missing];
66
- if (cur > best_cnt) {
67
- best_cnt = cur;
68
- best_missing = missing;
69
- }
70
- }
71
- }
72
- }
73
- }
74
-
75
- /* ---------- right distance candidate j = k - hi ---------- */
76
- j = k - hi; // right‑hand candidate, must be > i and not the same as left one
77
- if (j > i && j != i + hi) {
78
- int a = s - hi;
79
- int b = hi;
80
- int hj = H[j];
81
- if (hj == a || hj == b || hj == s) {
82
- if (! (a != b && hi == hj)) {
83
- int missing = 2 * s - hi - hj;
84
- if (1 <= missing && missing <= max_missing) {
85
- if (last[missing] != version) {
86
- cnt[missing] = 1;
87
- last[missing] = version;
88
- } else {
89
- ++cnt[missing];
90
- }
91
- int cur = cnt[missing];
92
- if (cur > best_cnt) {
93
- best_cnt = cur;
94
- best_missing = missing;
95
- }
96
- }
97
- }
98
- }
99
- }
100
- } // end for i
101
-
102
- if (best_cnt > 0) {
103
- H[k] = best_missing;
104
- total_T += best_cnt;
105
- } else {
106
- std::uniform_int_distribution<int> dist(0, static_cast<int>(useful_vals.size()) - 1);
107
- H[k] = useful_vals[dist(rng)];
108
- }
109
- }
110
-
111
- return {std::move(H), total_T};
112
- }
113
-
114
- /* ------------------------------------------------------------------ */
115
- /* Main routine requested by the problem statement. */
116
- /* ------------------------------------------------------------------ */
117
- std::vector<int> construct_range(int M, int K)
118
- {
119
- /* ---- 1. decide N ------------------------------------------------ */
120
- int N = std::max(3, M);
121
- if (N > M) N = M;
122
- // after this: 3 <= N <= M (or N = M when M < 3)
123
-
124
- const int max_h = N - 1; // allowed heights are 1 … max_h
125
-
126
- /* ---- 2. useful fallback values ---------------------------------- */
127
- std::vector<int> useful_vals;
128
- int limit = std::min(N, 10);
129
- for (int v = 1; v <= limit; ++v) useful_vals.push_back(v);
130
- if (max_h >= 1 && std::find(useful_vals.begin(), useful_vals.end(), max_h) == useful_vals.end())
131
- useful_vals.push_back(max_h);
132
-
133
- /* ---- 3. deterministic seeds -------------------------------------- */
134
- std::vector<std::pair<int, int>> seeds = {
135
- {1, 1}, {1, 2}, {2, 1}, {2, 2}
136
- };
137
- if (max_h >= 1) seeds.emplace_back(max_h, max_h);
138
- if (max_h >= 2) seeds.emplace_back(max_h - 1, max_h - 1);
139
- seeds.emplace_back(max_h, 1);
140
- seeds.emplace_back(1, max_h);
141
-
142
- /* ---- 4. a few random seeds (fixed RNG) -------------------------- */
143
- std::mt19937 rnd(123456);
144
- std::uniform_int_distribution<int> dist01(1, max_h);
145
- for (int i = 0; i < 3; ++i) {
146
- int h0 = dist01(rnd);
147
- int h1 = dist01(rnd);
148
- seeds.emplace_back(h0, h1);
149
- }
150
-
151
- /* ---- 5. deduplicate ---------------------------------------------- */
152
- std::vector<std::pair<int, int>> uniq_seeds;
153
- {
154
- std::vector<bool> seen((max_h + 1) * (max_h + 1), false); // cheap, because max_h is at most a few thousands
155
- for (auto &p : seeds) {
156
- int h0 = std::max(1, std::min(max_h, p.first));
157
- int h1 = std::max(1, std::min(max_h, p.second));
158
- int idx = (h0 - 1) * (max_h + 1) + (h1 - 1);
159
- if (!seen[idx]) {
160
- seen[idx] = true;
161
- uniq_seeds.emplace_back(h0, h1);
162
- }
163
- }
164
- }
165
- seeds.swap(uniq_seeds);
166
-
167
- /* ---- 6. try every seed, keep the best one ----------------------- */
168
- std::vector<int> best_H;
169
- long long best_T = -1;
170
-
171
- std::mt19937 rng(123456); // same RNG for the fallback values
172
- for (const auto &seed : seeds) {
173
- int h0 = std::max(1, std::min(max_h, seed.first));
174
- int h1 = std::max(1, std::min(max_h, seed.second));
175
-
176
- auto [H, T] = greedy_builder(N, h0, h1, useful_vals, rng);
177
- if (T > best_T) {
178
- best_T = T;
179
- best_H = H; // copy
180
- if (best_T >= K) break; // early exit when we already have enough
181
- }
182
- }
183
-
184
- /* ---- 7. final clamping (safety) ---------------------------------- */
185
- for (int &v : best_H) {
186
- if (v < 1) v = 1;
187
- else if (v > max_h) v = max_h;
188
- }
189
-
190
- if (static_cast<int>(best_H.size()) > N)
191
- best_H.resize(N);
192
- else if (static_cast<int>(best_H.size()) < N)
193
- best_H.resize(N, 1); // should not happen, but just in case
194
-
195
- return best_H;
196
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ioi2025/triples-part2-subtask4.cpp DELETED
@@ -1,122 +0,0 @@
1
- #include <vector>
2
- #include <algorithm> // std::min, std::max
3
-
4
- std::vector<int> construct_range(int M, int /* K */)
5
- {
6
- // -----------------------------------------------------------------
7
- // 1) decide the final length N and the maximal allowed height
8
- // -----------------------------------------------------------------
9
- int N = std::max(3, M);
10
- if (N > M) // this makes N = M when M < 3
11
- N = M;
12
-
13
- int max_allowed = N - 1; // heights are in [1 .. max_allowed]
14
-
15
- // radius of the sliding window
16
- int D = std::min(3500, (N - 1) / 2);
17
- int twoD = 2 * D;
18
-
19
- // -----------------------------------------------------------------
20
- // 2) data structures
21
- // -----------------------------------------------------------------
22
- std::vector<int> H(N, 0);
23
- H[0] = 1;
24
- if (N > 1)
25
- H[1] = 2; // second peak gets a different height
26
-
27
- // versioned counters for the “missing’’ height
28
- std::vector<int> cnt(max_allowed + 1, 0);
29
- std::vector<int> last(max_allowed + 1, 0);
30
- int version = 0; // increased for every k
31
- int total = 0; // lower bound on the number of triples
32
-
33
- // -----------------------------------------------------------------
34
- // 3) greedy construction
35
- // -----------------------------------------------------------------
36
- for (int k = 2; k < N; ++k) {
37
- ++version;
38
- int i_start = k - twoD;
39
- if (i_start < 0) i_start = 0;
40
-
41
- int best_cnt = 0;
42
- int best_missing = 1; // default if nothing is found
43
-
44
- // scan the recent window [i_start, k)
45
- for (int i = i_start; i < k; ++i) {
46
- int hi = H[i];
47
- int s = k - i; // distance i → k
48
- if (hi >= s) continue; // cannot be used, skip
49
-
50
- // -------------------------------------------------------------
51
- // left candidate: j = i + hi
52
- // -------------------------------------------------------------
53
- int j = i + hi; // always < k because hi < s
54
- int hj = H[j];
55
- int a = hi;
56
- int b = s - hi;
57
- // (hj == a or hj == b or hj == s) and not (a != b && hi == hj)
58
- if ((hj == a || hj == b || hj == s) &&
59
- !(a != b && hi == hj)) {
60
- int missing = 2 * s - hi - hj;
61
- if (1 <= missing && missing <= max_allowed) {
62
- if (last[missing] != version) {
63
- cnt[missing] = 1;
64
- last[missing] = version;
65
- } else {
66
- ++cnt[missing];
67
- }
68
- int cur = cnt[missing];
69
- if (cur > best_cnt) {
70
- best_cnt = cur;
71
- best_missing = missing;
72
- }
73
- }
74
- }
75
-
76
- // -------------------------------------------------------------
77
- // right candidate: j2 = k - hi (different from the left one)
78
- // -------------------------------------------------------------
79
- int j2 = k - hi;
80
- if (j2 > i && j2 != i + hi) {
81
- hj = H[j2];
82
- a = s - hi;
83
- b = hi;
84
- if ((hj == a || hj == b || hj == s) &&
85
- !(a != b && hi == hj)) {
86
- int missing = 2 * s - hi - hj;
87
- if (1 <= missing && missing <= max_allowed) {
88
- if (last[missing] != version) {
89
- cnt[missing] = 1;
90
- last[missing] = version;
91
- } else {
92
- ++cnt[missing];
93
- }
94
- int cur = cnt[missing];
95
- if (cur > best_cnt) {
96
- best_cnt = cur;
97
- best_missing = missing;
98
- }
99
- }
100
- }
101
- }
102
- } // end for i
103
-
104
- // choose the best missing height (or 1 if nothing helped)
105
- if (best_cnt > 0) {
106
- H[k] = best_missing;
107
- total += best_cnt;
108
- } else {
109
- H[k] = 1;
110
- }
111
- }
112
-
113
- // -----------------------------------------------------------------
114
- // 4) safety clamp (normally already satisfied)
115
- // -----------------------------------------------------------------
116
- for (int &v : H) {
117
- if (v < 1) v = 1;
118
- else if (v > max_allowed) v = max_allowed;
119
- }
120
-
121
- return H; // the constructed range
122
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ioi2025/triples-part2-subtask5.cpp DELETED
@@ -1,141 +0,0 @@
1
- #include <bits/stdc++.h>
2
- using namespace std;
3
-
4
- /* ------------------------------------------------------------
5
- Greedy construction of one block
6
- ------------------------------------------------------------ */
7
- static pair<vector<int>, long long> build_block(int B, int D)
8
- {
9
- /* H[0] … H[B‑1] – heights, 1 ≤ H[i] ≤ B‑1 */
10
- vector<int> H(B, 0);
11
- H[0] = 1;
12
- H[1] = 1; // any value 1 … B‑1 would work
13
-
14
- const int max_allowed = B - 1;
15
- int max_missing = 4 * D;
16
- if (max_missing > max_allowed) max_missing = max_allowed;
17
- if (max_missing < 1) max_missing = 1; // at least 1
18
-
19
- /* versioned counters for “missing” values (size = max_missing+1) */
20
- vector<int> cnt(max_missing + 1, 0);
21
- vector<int> last(max_missing + 1, 0);
22
- int version = 0;
23
-
24
- long long total = 0; // total number of triples created in the block
25
- const int twoD = 2 * D;
26
-
27
- for (int k = 2; k < B; ++k) {
28
- ++version; // start a fresh counting round for this k
29
- int best_cnt = 0;
30
- int best_missing = 1; // default – will be overwritten if we find a better one
31
-
32
- /* the distance from the leftmost i we have to examine.
33
- i must satisfy k‑i ≤ 2·D, i.e. i ≥ k‑2·D */
34
- int i_start = k - twoD;
35
- if (i_start < 0) i_start = 0;
36
-
37
- for (int i = i_start; i < k; ++i) {
38
- int hi = H[i];
39
- int s = k - i; // distance i → k
40
- if (hi >= s) continue; // hi must be smaller than the distance
41
-
42
- /* ----------------------------------------------------
43
- left candidate : j = i + hi (the point that would be
44
- exactly hi units to the right of i)
45
- ---------------------------------------------------- */
46
- int j = i + hi;
47
- if (j < k) {
48
- int a = hi;
49
- int b = s - hi;
50
- int hj = H[j];
51
- if ( (hj == a || hj == b || hj == s) &&
52
- !(a != b && hi == hj) ) // avoid the “a≠b && hi==hj” case
53
- {
54
- int missing = 2 * s - hi - hj; // how many triples this choice would give
55
- if (1 <= missing && missing <= max_missing) {
56
- if (last[missing] != version) {
57
- cnt[missing] = 1;
58
- last[missing] = version;
59
- } else {
60
- ++cnt[missing];
61
- }
62
- if (cnt[missing] > best_cnt) {
63
- best_cnt = cnt[missing];
64
- best_missing = missing;
65
- }
66
- }
67
- }
68
- }
69
-
70
- /* ----------------------------------------------------
71
- right candidate : j2 = k – hi (the point that would be
72
- exactly hi units to the left of k)
73
- ---------------------------------------------------- */
74
- int j2 = k - hi;
75
- if (j2 > i && j2 != i + hi) { // must be a *different* position
76
- int a = s - hi;
77
- int b = hi;
78
- int hj = H[j2];
79
- if ( (hj == a || hj == b || hj == s) &&
80
- !(a != b && hi == hj) )
81
- {
82
- int missing = 2 * s - hi - hj;
83
- if (1 <= missing && missing <= max_missing) {
84
- if (last[missing] != version) {
85
- cnt[missing] = 1;
86
- last[missing] = version;
87
- } else {
88
- ++cnt[missing];
89
- }
90
- if (cnt[missing] > best_cnt) {
91
- best_cnt = cnt[missing];
92
- best_missing = missing;
93
- }
94
- }
95
- }
96
- }
97
- } // end for i
98
-
99
- if (best_cnt > 0) {
100
- H[k] = best_missing;
101
- total += best_cnt;
102
- } else {
103
- H[k] = 1; // fall‑back – the smallest admissible value
104
- }
105
- } // end for k
106
-
107
- return {H, total};
108
- }
109
-
110
- /* ------------------------------------------------------------
111
- Whole range construction
112
- ------------------------------------------------------------ */
113
- vector<int> construct_range(int M, int K)
114
- {
115
- int N = M;
116
- if (N < 3) N = 3;
117
-
118
- /* block size – a good compromise between speed and strength */
119
- int B = min(N, 25000);
120
-
121
- /* window size – large enough to create many triples but not too large */
122
- int D = (B - 1) / 2;
123
- if (D > 4000) D = 4000;
124
- if (D == 0) D = 1;
125
-
126
- /* Build one block and repeat it to fill the whole range */
127
- auto [block, /*unused*/] = build_block(B, D);
128
-
129
- int reps = N / B;
130
- int rest = N % B;
131
-
132
- vector<int> H;
133
- H.reserve(N);
134
- for (int r = 0; r < reps; ++r) H.insert(H.end(), block.begin(), block.end());
135
- H.insert(H.end(), block.begin(), block.begin() + rest); // add the leftover part
136
- H.resize(N); // ensure length exactly N
137
-
138
- /* At this point every H[i] already satisfies
139
- 1 ≤ H[i] ≤ B‑1 ≤ N‑1, i.e. the required bounds. */
140
- return H;
141
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ioi2025/triples-part2-subtask6.cpp DELETED
@@ -1,131 +0,0 @@
1
- #include <vector>
2
- #include <algorithm> // for std::min, std::max
3
- #include <cstddef> // for std::size_t
4
- #include <cassert>
5
-
6
- static std::vector<int> greedy_block(int B, int D)
7
- {
8
- /* H will hold the heights for the block, 0‑based indices */
9
- std::vector<int> H(B, 0);
10
-
11
- const int max_missing = B - 1; // allowed values: 1 … max_missing
12
- const int twoD = 2 * D;
13
-
14
- /* temporary counters, version stamps and the version counter */
15
- std::vector<int> cnt(max_missing + 1, 0);
16
- std::vector<int> last(max_missing + 1, 0);
17
- int version = 0;
18
-
19
- for (int k = 0; k < B; ++k) {
20
- ++version; // start a new “window”
21
-
22
- int i_start = k - twoD;
23
- if (i_start < 0) i_start = 0;
24
-
25
- int best_cnt = 0;
26
- int best_missing = 1; // any legal value if we cannot improve
27
-
28
- for (int i = i_start; i < k; ++i) {
29
- int hi = H[i];
30
- int s = k - i; // distance i → k
31
- if (hi >= s) continue; // hi cannot be used
32
-
33
- /* ----------- left side: j = i + hi -------------------------- */
34
- int j = i + hi;
35
- if (j < k) {
36
- int hj = H[j];
37
- int a = hi;
38
- int b = s - hi;
39
-
40
- bool ok = (hj == a) || (hj == b) || (hj == s);
41
- ok = ok && !(a != b && hi == hj); // forbid the symmetric case
42
-
43
- if (ok) {
44
- int miss = 2 * s - hi - hj; // the “missing” value
45
- if (miss >= 1 && miss <= max_missing) {
46
- if (last[miss] != version) {
47
- cnt[miss] = 1;
48
- last[miss] = version;
49
- } else {
50
- ++cnt[miss];
51
- }
52
-
53
- if (cnt[miss] > best_cnt) {
54
- best_cnt = cnt[miss];
55
- best_missing = miss;
56
- }
57
- }
58
- }
59
- }
60
-
61
- /* ----------- right side: j = k - hi ------------------------- */
62
- int j2 = k - hi;
63
- if (j2 > i && j2 != i + hi) {
64
- int hj = H[j2];
65
- int a = s - hi;
66
- int b = hi;
67
-
68
- bool ok = (hj == a) || (hj == b) || (hj == s);
69
- ok = ok && !(a != b && hi == hj); // same symmetric check
70
-
71
- if (ok) {
72
- int miss = 2 * s - hi - hj;
73
- if (miss >= 1 && miss <= max_missing) {
74
- if (last[miss] != version) {
75
- cnt[miss] = 1;
76
- last[miss] = version;
77
- } else {
78
- ++cnt[miss];
79
- }
80
-
81
- if (cnt[miss] > best_cnt) {
82
- best_cnt = cnt[miss];
83
- best_missing = miss;
84
- }
85
- }
86
- }
87
- }
88
- } // end of inner loop over i
89
-
90
- /* write the height for position k */
91
- if (best_cnt > 0)
92
- H[k] = best_missing;
93
- else
94
- H[k] = 1; // any legal value is fine
95
- }
96
-
97
- return H;
98
- }
99
-
100
- /* ------------------------------------------------------------------ */
101
- /* Public API – exactly the signature required by the task */
102
- /* ------------------------------------------------------------------ */
103
- std::vector<int> construct_range(int M, int K)
104
- {
105
- (void)K; // avoid unused‑parameter warning
106
-
107
- const int N = std::max(3, M); // final length of the range
108
- const int B = std::min(N, 20000); // block size (greedy works better with a limit)
109
- const int D = std::min(4000, (B - 1) / 2); // half‑window size
110
-
111
- std::vector<int> block = greedy_block(B, D);
112
-
113
- const int repeats = N / B;
114
- const int rest = N % B;
115
-
116
- std::vector<int> H;
117
- H.reserve(N);
118
- for (int r = 0; r < repeats; ++r)
119
- H.insert(H.end(), block.begin(), block.end());
120
- H.insert(H.end(), block.begin(), block.begin() + rest); // the possible tail
121
-
122
- /* Clamp to the allowed interval [1, N‑1] – this is a harmless safety net. */
123
- const int max_allowed = N - 1;
124
- for (int &v : H) {
125
- if (v < 1) v = 1;
126
- else if (v > max_allowed) v = max_allowed;
127
- }
128
-
129
- H.resize(N); // just in case something went wrong (should already be N)
130
- return H;
131
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ioi2025/worldmap.cpp DELETED
@@ -1,202 +0,0 @@
1
- #include <bits/stdc++.h>
2
- using namespace std;
3
-
4
- /* ----------------------------------------------------------------------
5
- create_map
6
- ---------------------------------------------------------------------- */
7
- vector<vector<int>> create_map(int N, int M,
8
- vector<int> A, vector<int> B)
9
- {
10
- /* --------------------------------------------------------------
11
- 0‑based adjacency matrix and list of edges
12
- -------------------------------------------------------------- */
13
- vector<vector<char>> adj(N, vector<char>(N, 0));
14
- vector<pair<int,int>> edges;
15
- edges.reserve(M);
16
-
17
- for (int k = 0; k < M; ++k) {
18
- int u = A[k] - 1; // to 0‑based
19
- int v = B[k] - 1;
20
- adj[u][v] = adj[v][u] = 1;
21
- edges.emplace_back(u, v);
22
- }
23
- const int M_edges = static_cast<int>(edges.size());
24
-
25
- /* --------------------------------------------------------------
26
- edge_id[u][v] (only for u < v) → index of the edge in `edges`
27
- -------------------------------------------------------------- */
28
- vector<vector<int>> edge_id(N, vector<int>(N, -1));
29
- for (int idx = 0; idx < M_edges; ++idx) {
30
- int u = edges[idx].first;
31
- int v = edges[idx].second;
32
- if (u > v) swap(u, v);
33
- edge_id[u][v] = idx;
34
- }
35
-
36
- /* --------------------------------------------------------------
37
- neighbour_mask[i] – bit mask of colours that may be placed
38
- next to a cell whose colour is i (loops + the 4‑neighbours)
39
- -------------------------------------------------------------- */
40
- vector<uint64_t> neighbour_mask(N, 0);
41
- for (int i = 0; i < N; ++i) {
42
- uint64_t mask = 1ULL << i; // the colour itself
43
- for (int j = 0; j < N; ++j)
44
- if (adj[i][j]) mask |= (1ULL << j);
45
- neighbour_mask[i] = mask;
46
- }
47
- const uint64_t all_mask = (N == 64) ? ~0ULL : ((1ULL << N) - 1ULL);
48
-
49
- /* --------------------------------------------------------------
50
- board size K (smallest board that could possibly work)
51
- -------------------------------------------------------------- */
52
- int K0 = static_cast<int>(sqrt((double)N));
53
- while (K0 * K0 < N) ++K0; // ceil(sqrt(N))
54
-
55
- int Kedge = 0;
56
- while (2 * Kedge * (Kedge - 1) < M_edges) ++Kedge;
57
-
58
- int K = max(K0, Kedge);
59
- K = max(K, 2 * N); // a bit of spare space
60
- if (K > 240) K = 240; // safety cap
61
-
62
- /* --------------------------------------------------------------
63
- random generator – used for the “several random attempts”
64
- -------------------------------------------------------------- */
65
- std::mt19937 rng(
66
- static_cast<unsigned>(chrono::steady_clock::now()
67
- .time_since_epoch()
68
- .count()));
69
-
70
- const int MAX_ATTEMPTS = 500;
71
-
72
- for (int attempt = 0; attempt < MAX_ATTEMPTS; ++attempt) {
73
- /* ----- fresh board for this attempt ---------------------- */
74
- vector<vector<int>> grid(K, vector<int>(K, -1));
75
- uint64_t used_colours = 0; // bit mask of colours already used
76
- vector<char> covered(M_edges, 0);
77
- int covered_cnt = 0;
78
- bool ok = true;
79
-
80
- /* ----- greedy filling of the K×K board ------------------- */
81
- for (int i = 0; i < K && ok; ++i) {
82
- for (int j = 0; j < K; ++j) {
83
- uint64_t allowed = all_mask; // colours allowed by neighbours
84
-
85
- if (i > 0) {
86
- int top = grid[i-1][j];
87
- allowed &= neighbour_mask[top];
88
- }
89
- if (j > 0) {
90
- int left = grid[i][j-1];
91
- allowed &= neighbour_mask[left];
92
- }
93
-
94
- if (allowed == 0) { // dead end → restart whole board
95
- ok = false;
96
- break;
97
- }
98
-
99
- uint64_t missing = all_mask & ~used_colours;
100
- uint64_t missing_allowed = allowed & missing;
101
-
102
- /* ----- pick the colour with the best gain ---------- */
103
- int best_gain = -1;
104
- vector<int> candidates;
105
-
106
- uint64_t mask = allowed;
107
- while (mask) {
108
- uint64_t lsb = mask & -mask;
109
- int c = __builtin_ctzll(lsb); // colour index (0‑based)
110
- mask ^= lsb;
111
-
112
- int gain = 0;
113
-
114
- /* edges that would become covered if we use colour c */
115
- if (i > 0) {
116
- int nt = grid[i-1][j];
117
- if (nt != c && adj[nt][c]) {
118
- int u = min(nt, c), v = max(nt, c);
119
- int eid = edge_id[u][v];
120
- if (eid != -1 && !covered[eid]) ++gain;
121
- }
122
- }
123
- if (j > 0) {
124
- int nl = grid[i][j-1];
125
- if (nl != c && adj[nl][c]) {
126
- int u = min(nl, c), v = max(nl, c);
127
- int eid = edge_id[u][v];
128
- if (eid != -1 && !covered[eid]) ++gain;
129
- }
130
- }
131
-
132
- /* huge bonus for a colour that has never been used */
133
- if (missing_allowed && ( (1ULL << c) & missing_allowed ))
134
- gain += 1000;
135
-
136
- if (gain > best_gain) {
137
- best_gain = gain;
138
- candidates.clear();
139
- candidates.push_back(c);
140
- } else if (gain == best_gain) {
141
- candidates.push_back(c);
142
- }
143
- } // end while(mask)
144
-
145
- /* ----- random tie‑break among the best candidates --- */
146
- uniform_int_distribution<int> dist(0, (int)candidates.size() - 1);
147
- int chosen = candidates[dist(rng)];
148
-
149
- /* ----- store the colour -------------------------------- */
150
- grid[i][j] = chosen;
151
- used_colours |= (1ULL << chosen);
152
-
153
- /* ----- mark newly created edges ------------------------ */
154
- if (i > 0) {
155
- int nt = grid[i-1][j];
156
- if (nt != chosen && adj[nt][chosen]) {
157
- int u = min(nt, chosen), v = max(nt, chosen);
158
- int eid = edge_id[u][v];
159
- if (eid != -1 && !covered[eid]) {
160
- covered[eid] = 1;
161
- ++covered_cnt;
162
- }
163
- }
164
- }
165
- if (j > 0) {
166
- int nl = grid[i][j-1];
167
- if (nl != chosen && adj[nl][chosen]) {
168
- int u = min(nl, chosen), v = max(nl, chosen);
169
- int eid = edge_id[u][v];
170
- if (eid != -1 && !covered[eid]) {
171
- covered[eid] = 1;
172
- ++covered_cnt;
173
- }
174
- }
175
- }
176
- } // end for j
177
- } // end for i
178
-
179
- if (!ok) continue;
180
- if (used_colours != all_mask) continue; // not all colours used
181
- if (covered_cnt != M_edges) continue; // some edges still uncovered
182
-
183
- /* ----- SUCCESS – convert to 1‑based output ---------------- */
184
- vector<vector<int>> answer(K, vector<int>(K));
185
- for (int i = 0; i < K; ++i)
186
- for (int j = 0; j < K; ++j)
187
- answer[i][j] = grid[i][j] + 1; // back to 1‑based
188
- return answer;
189
- } // end for attempts
190
-
191
- /* --------------------------------------------------------------
192
- Very unlikely fallback – deterministic construction
193
- -------------------------------------------------------------- */
194
- int Kfallback = max(2 * N, 2);
195
- Kfallback = min(Kfallback, 240);
196
- vector<vector<int>> grid(Kfallback, vector<int>(Kfallback, 1));
197
- int limit = min(N, Kfallback);
198
- for (int i = 0; i < limit; ++i)
199
- grid[i][i] = i + 1; // put distinct colours on the diagonal
200
-
201
- return grid;
202
- }