Skip to content

Commit 4c4e406

Browse files
committed
sprint5
1 parent 0cf4a82 commit 4c4e406

4 files changed

Lines changed: 467 additions & 0 deletions

File tree

input.txt

Whitespace-only changes.

output.txt

Whitespace-only changes.
Lines changed: 291 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
import java.io.EOFException;
2+
import java.io.IOException;
3+
import java.io.InputStream;
4+
import java.io.OutputStream;
5+
6+
public class PyramidSort {
7+
8+
/*
9+
* Принцип работы алгоритма:
10+
* 1) Считываем всех участников в массив.
11+
* 2) Сортируем массив пирамидальной сортировкой.
12+
* 3) Для этого сначала строим max-heap, где наверху находится не лучший,
13+
* а худший по условию участник. Это удобно для heapsort: на каждой
14+
* итерации мы ставим корень кучи в конец ещё неотсортированной части.
15+
* 4) Участник a считается хуже участника b, если:
16+
* - a решил меньше задач;
17+
* - при равенстве решённых задач у a штраф больше;
18+
* - при равенстве и задач, и штрафа логин a лексикографически больше.
19+
* 5) После каждого обмена восстанавливаем свойство кучи просеиванием вниз.
20+
*
21+
* Почему алгоритм корректен:
22+
* 1) Компаратор точно совпадает с порядком из условия, только в обратном
23+
* направлении: "больше" в куче означает "хуже в итоговой таблице".
24+
* 2) Поэтому в корне max-heap всегда лежит худший участник среди всех
25+
* элементов текущей кучи.
26+
* 3) На каждом шаге heapsort мы меняем корень с последним элементом
27+
* неотсортированной части. Значит, этот худший участник встаёт ровно
28+
* на своё окончательное место.
29+
* 4) После просеивания вниз куча снова корректна.
30+
* 5) Повторяя этот процесс, получаем массив, отсортированный от лучшего
31+
* участника к худшему.
32+
*
33+
* Временная сложность:
34+
* - построение кучи: O(n);
35+
* - n операций извлечения максимума: O(n log n);
36+
* - итоговая сложность: O(n log n).
37+
*
38+
* Пространственная сложность:
39+
* - O(n) на хранение массива участников;
40+
* - дополнительная память алгоритма сортировки: O(1).
41+
*/
42+
43+
static final class Participant {
44+
String login;
45+
int solved;
46+
int penalty;
47+
48+
Participant(String login, int solved, int penalty) {
49+
this.login = login;
50+
this.solved = solved;
51+
this.penalty = penalty;
52+
}
53+
}
54+
55+
static void solve(Participant[] a) {
56+
heapSort(a);
57+
}
58+
59+
static int compare(Participant a, Participant b) {
60+
if (a.solved != b.solved) {
61+
return Integer.compare(b.solved, a.solved);
62+
}
63+
if (a.penalty != b.penalty) {
64+
return Integer.compare(a.penalty, b.penalty);
65+
}
66+
return a.login.compareTo(b.login);
67+
}
68+
69+
static void heapSort(Participant[] a) {
70+
int n = a.length;
71+
72+
for (int i = n / 2 - 1; i >= 0; i--) {
73+
siftDown(a, i, n);
74+
}
75+
76+
for (int end = n - 1; end > 0; end--) {
77+
swap(a, 0, end);
78+
siftDown(a, 0, end);
79+
}
80+
}
81+
82+
static void siftDown(Participant[] a, int i, int size) {
83+
while (true) {
84+
int left = i * 2 + 1;
85+
if (left >= size) {
86+
return;
87+
}
88+
89+
int right = left + 1;
90+
int worst = left;
91+
92+
if (right < size && compare(a[right], a[left]) > 0) {
93+
worst = right;
94+
}
95+
96+
if (compare(a[worst], a[i]) <= 0) {
97+
return;
98+
}
99+
100+
swap(a, i, worst);
101+
i = worst;
102+
}
103+
}
104+
105+
static void swap(Participant[] a, int i, int j) {
106+
Participant tmp = a[i];
107+
a[i] = a[j];
108+
a[j] = tmp;
109+
}
110+
111+
static final class FastIn {
112+
private final InputStream in;
113+
private final byte[] buf = new byte[1 << 16];
114+
private int ptr = 0;
115+
private int len = 0;
116+
117+
FastIn(InputStream in) {
118+
this.in = in;
119+
}
120+
121+
private int read() throws IOException {
122+
if (ptr >= len) {
123+
len = in.read(buf);
124+
ptr = 0;
125+
if (len <= 0) {
126+
return -1;
127+
}
128+
}
129+
return buf[ptr++];
130+
}
131+
132+
int nextInt() throws IOException {
133+
int c;
134+
do {
135+
c = read();
136+
if (c == -1) {
137+
throw new EOFException("Unexpected EOF");
138+
}
139+
} while (c <= ' ');
140+
141+
int sign = 1;
142+
if (c == '-') {
143+
sign = -1;
144+
c = read();
145+
}
146+
147+
int val = 0;
148+
while (c > ' ') {
149+
val = val * 10 + (c - '0');
150+
c = read();
151+
}
152+
return val * sign;
153+
}
154+
155+
String next() throws IOException {
156+
int c;
157+
do {
158+
c = read();
159+
if (c == -1) {
160+
throw new EOFException("Unexpected EOF");
161+
}
162+
} while (c <= ' ');
163+
164+
byte[] tmp = new byte[32];
165+
int n = 0;
166+
167+
while (c > ' ') {
168+
if (n == tmp.length) {
169+
byte[] next = new byte[tmp.length * 2];
170+
System.arraycopy(tmp, 0, next, 0, tmp.length);
171+
tmp = next;
172+
}
173+
tmp[n++] = (byte) c;
174+
c = read();
175+
if (c == -1) {
176+
break;
177+
}
178+
}
179+
180+
return new String(tmp, 0, n);
181+
}
182+
}
183+
184+
static final class FastOut {
185+
private final OutputStream out;
186+
private final byte[] buf = new byte[1 << 16];
187+
private int ptr = 0;
188+
189+
FastOut(OutputStream out) {
190+
this.out = out;
191+
}
192+
193+
void writeByte(int b) throws IOException {
194+
if (ptr == buf.length) {
195+
flush();
196+
}
197+
buf[ptr++] = (byte) b;
198+
}
199+
200+
void writeString(String s) throws IOException {
201+
for (int i = 0; i < s.length(); i++) {
202+
writeByte(s.charAt(i));
203+
}
204+
}
205+
206+
void flush() throws IOException {
207+
out.write(buf, 0, ptr);
208+
ptr = 0;
209+
}
210+
}
211+
212+
private static void run() throws Exception {
213+
FastIn in = new FastIn(System.in);
214+
FastOut out = new FastOut(System.out);
215+
216+
int n = in.nextInt();
217+
Participant[] a = new Participant[n];
218+
219+
for (int i = 0; i < n; i++) {
220+
String login = in.next();
221+
int solved = in.nextInt();
222+
int penalty = in.nextInt();
223+
a[i] = new Participant(login, solved, penalty);
224+
}
225+
226+
solve(a);
227+
228+
for (Participant p : a) {
229+
out.writeString(p.login);
230+
out.writeByte('\n');
231+
}
232+
out.flush();
233+
}
234+
235+
private static void test() {
236+
Participant[] a1 = new Participant[] {
237+
new Participant("alla", 4, 100),
238+
new Participant("gena", 6, 1000),
239+
new Participant("gosha", 2, 90),
240+
new Participant("rita", 2, 90),
241+
new Participant("timofey", 4, 80)
242+
};
243+
solve(a1);
244+
assertEq("gena", a1[0].login);
245+
assertEq("timofey", a1[1].login);
246+
assertEq("alla", a1[2].login);
247+
assertEq("gosha", a1[3].login);
248+
assertEq("rita", a1[4].login);
249+
250+
Participant[] a2 = new Participant[] {
251+
new Participant("alla", 0, 0),
252+
new Participant("gena", 0, 0),
253+
new Participant("gosha", 0, 0),
254+
new Participant("rita", 0, 0),
255+
new Participant("timofey", 0, 0)
256+
};
257+
solve(a2);
258+
assertEq("alla", a2[0].login);
259+
assertEq("gena", a2[1].login);
260+
assertEq("gosha", a2[2].login);
261+
assertEq("rita", a2[3].login);
262+
assertEq("timofey", a2[4].login);
263+
264+
Participant[] a3 = new Participant[] {
265+
new Participant("b", 1, 10),
266+
new Participant("a", 1, 10),
267+
new Participant("c", 2, 100)
268+
};
269+
solve(a3);
270+
assertEq("c", a3[0].login);
271+
assertEq("a", a3[1].login);
272+
assertEq("b", a3[2].login);
273+
274+
System.out.println("Test OK");
275+
}
276+
277+
static void assertEq(String expected, String actual) {
278+
if (!expected.equals(actual)) {
279+
throw new AssertionError("Expected=" + expected + ", actual=" + actual);
280+
}
281+
}
282+
283+
public static void main(String[] args) throws Exception {
284+
if (System.getProperty("os.name").startsWith("Windows")) {
285+
test();
286+
} else {
287+
run();
288+
}
289+
}
290+
}
291+

0 commit comments

Comments
 (0)