Skip to content

Commit 39b46e3

Browse files
committed
Dodano rozwiązanie zadania 'Pojemniki' z XXXI OI
1 parent 2c82e86 commit 39b46e3

File tree

1 file changed

+67
-0
lines changed
  • rozwiazania/xxxi/etap2/dzien2/poj

1 file changed

+67
-0
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Rozwiązanie zadania 'Pojemniki' z II etapu XXXI OI.
2+
// Autor rozwiązania: Paweł Putra
3+
// Złożoność czasowa: O(n * log(n))
4+
// Złożoność pamięciowa: O(n).
5+
// Punkty: 100 (upsolve)
6+
7+
#include <bits/stdc++.h>
8+
using namespace std;
9+
using ll = long long;
10+
int32_t main() {
11+
ios_base::sync_with_stdio(0);
12+
int n;
13+
ll k;
14+
cin >> n >> k;
15+
16+
multiset<pair<ll, int>> s;
17+
for (int i = 1; i <= n; i++) {
18+
ll x;
19+
cin >> x;
20+
s.insert({x, i});
21+
}
22+
23+
vector<vector<pair<int,ll>>> pojemniki;
24+
while (!s.empty()) {
25+
auto [min_ile, min_idx] = *s.begin();
26+
// Jeśli minimum jest większe niż k, to suma objętości jest większa niż n * k.
27+
if (min_ile > k) {
28+
cout << "NIE\n";
29+
return 0;
30+
}
31+
32+
// Jeśli rozwiązanie istnieje, to istnieje też rozwiązanie,
33+
// w którym składnik o najmniejszej objętości jest tylko w jednym pojemniku.
34+
// Dowód:
35+
// Załóżmy, że w jakimś rozwiązaniu są dwa pojemniki, w których jest ten składnik.
36+
// Zawsze możemy przenieść ten składnik z pojemnika, w którym jest go mniej do tego drugiego,
37+
// zamieniając go z resztą składnika drugiego. Zmieści się na pewno bo sumaryczna objętość
38+
// tego składnika nie przekracza k.
39+
pojemniki.push_back({{min_idx, min_ile}});
40+
ll zostalo = k - min_ile;
41+
if (zostalo > 0) {
42+
auto [max_ile, max_idx] = *(--s.end());
43+
if (max_idx != min_idx) {
44+
s.erase(--s.end());
45+
ll zabierane = min(max_ile, zostalo);
46+
if (zabierane < max_ile) {
47+
s.insert({max_ile - zostalo, max_idx});
48+
}
49+
pojemniki.back().push_back({max_idx, zabierane});
50+
}
51+
}
52+
53+
// Nie można zrobić s.erase(s.begin()) bo maks mógł stać się nowym minem.
54+
s.erase(s.find({min_ile, min_idx}));
55+
}
56+
57+
cout << "TAK\n";
58+
for (int i = 0; i < n; i++) {
59+
if (i >= pojemniki.size()) {
60+
cout << "0\n";
61+
continue;
62+
}
63+
cout << pojemniki[i].size() << " ";
64+
for (auto [idx, ile] : pojemniki[i]) cout << idx << " " << ile << " ";
65+
cout << "\n";
66+
}
67+
}

0 commit comments

Comments
 (0)