1+ import java .io .EOFException ;
2+ import java .io .IOException ;
3+ import java .io .InputStream ;
4+
5+ //https://contest.yandex.ru/contest/23815/run-report/160042811/
6+
7+ public class FastSort {
8+
9+ /*
10+ Принцип работы алгоритма:
11+ 1) Считываем n участников в массив.
12+ 2) Сортируем массив in-place быстрой сортировкой.
13+ 3) Определяем лучше участника методом boolean better(a, b) по правилам задачи:
14+ - у A решено больше задач;
15+ - при равенстве задач у A меньше штраф;
16+ - при равенстве штрафа логин A меньше лексикографически.
17+
18+ Почему алгоритм корректен:
19+ 1) Функция better(a, b) задаёт ровно тот порядок, который требуется в условии.
20+ 2) На каждом шаге quicksort мы делим массив относительно pivot:
21+ слева остаются элементы, которые должны идти не позже pivot,
22+ справа — элементы, которые должны идти не раньше pivot.
23+ 3) После этого рекурсивно сортируем обе части.
24+ 4) База рекурсии — отрезок длины 0 или 1, он уже отсортирован.
25+ Значит, весь массив будет отсортирован правильно.
26+
27+ Временная сложность: в среднем O(n log n), где n количество участников
28+
29+ Пространственная сложность: O(1) дополнительной памяти на перестановки,
30+ O(log n) в среднем на стек рекурсии.
31+ */
32+
33+ static class Participant {
34+ String login ;
35+ int solved ;
36+ int penalty ;
37+
38+ Participant (String login , int solved , int penalty ) {
39+ this .login = login ;
40+ this .solved = solved ;
41+ this .penalty = penalty ;
42+ }
43+ }
44+
45+ static boolean better (Participant a , Participant b ) {
46+ if (a .solved != b .solved ) {
47+ return a .solved > b .solved ;
48+ }
49+ if (a .penalty != b .penalty ) {
50+ return a .penalty < b .penalty ;
51+ }
52+ return a .login .compareTo (b .login ) < 0 ;
53+ }
54+
55+ static void swap (Participant [] a , int i , int j ) {
56+ Participant temp = a [i ];
57+ a [i ] = a [j ];
58+ a [j ] = temp ;
59+ }
60+
61+ static void quickSort (Participant [] a , int left , int right ) {
62+ while (left < right ) {
63+ int i = left ;
64+ int j = right ;
65+ Participant pivot = a [left + (right - left ) / 2 ];
66+
67+ while (i <= j ) {
68+ while (better (a [i ], pivot )) {
69+ i ++;
70+ }
71+ while (better (pivot , a [j ])) {
72+ j --;
73+ }
74+ if (i <= j ) {
75+ swap (a , i , j );
76+ i ++;
77+ j --;
78+ }
79+ }
80+
81+ if (j - left < right - i ) {
82+ if (left < j ) {
83+ quickSort (a , left , j );
84+ }
85+ left = i ;
86+ } else {
87+ if (i < right ) {
88+ quickSort (a , i , right );
89+ }
90+ right = j ;
91+ }
92+ }
93+ }
94+
95+ static String solve (Participant [] participants ) {
96+ if (participants .length > 1 ) {
97+ quickSort (participants , 0 , participants .length - 1 );
98+ }
99+
100+ StringBuilder sb = new StringBuilder ();
101+ for (Participant p : participants ) {
102+ sb .append (p .login ).append ('\n' );
103+ }
104+ return sb .toString ();
105+ }
106+
107+ static final class FastIn {
108+ private final InputStream in ;
109+ private final byte [] buffer = new byte [1 << 16 ];
110+ private int ptr = 0 ;
111+ private int len = 0 ;
112+
113+ FastIn (InputStream in ) {
114+ this .in = in ;
115+ }
116+
117+ private int read () throws IOException {
118+ if (ptr >= len ) {
119+ len = in .read (buffer );
120+ ptr = 0 ;
121+ if (len <= 0 ) {
122+ return -1 ;
123+ }
124+ }
125+ return buffer [ptr ++];
126+ }
127+
128+ int nextInt () throws IOException {
129+ int c ;
130+ do {
131+ c = read ();
132+ if (c == -1 ) {
133+ throw new EOFException ();
134+ }
135+ } while (c <= ' ' );
136+
137+ int value = 0 ;
138+ while (c > ' ' ) {
139+ value = value * 10 + (c - '0' );
140+ c = read ();
141+ }
142+ return value ;
143+ }
144+
145+ String next () throws IOException {
146+ int c ;
147+ do {
148+ c = read ();
149+ if (c == -1 ) {
150+ throw new EOFException ();
151+ }
152+ } while (c <= ' ' );
153+
154+ StringBuilder sb = new StringBuilder ();
155+ while (c > ' ' ) {
156+ sb .append ((char ) c );
157+ c = read ();
158+ }
159+ return sb .toString ();
160+ }
161+ }
162+
163+ private static void run () throws Exception {
164+ FastIn in = new FastIn (System .in );
165+
166+ int n = in .nextInt (); // n — количество участников
167+ Participant [] participants = new Participant [n ];
168+
169+ for (int i = 0 ; i < n ; i ++) {
170+ String login = in .next ();
171+ int solved = in .nextInt ();
172+ int penalty = in .nextInt ();
173+ participants [i ] = new Participant (login , solved , penalty );
174+ }
175+
176+ System .out .print (solve (participants ));
177+ }
178+
179+ private static void test () {
180+ Participant [] a = {new Participant ("alla" , 4 , 100 ), new Participant ("gena" , 6 , 1000 ), new Participant ("gosha" , 2 , 90 ), new Participant ("rita" , 2 , 90 ), new Participant ("timofey" , 4 , 80 )};
181+
182+ String expected = "gena\n timofey\n alla\n gosha\n rita\n " ;
183+ String actual = solve (a );
184+
185+ if (!expected .equals (actual )) {
186+ throw new AssertionError ("Expected:\n " + expected + "Actual:\n " + actual );
187+ }
188+
189+ System .out .println ("Test OK" );
190+ }
191+
192+ public static void main (String [] args ) throws Exception {
193+ if (System .getProperty ("os.name" ).startsWith ("Windows" )) {
194+ test ();
195+ } else {
196+ run ();
197+ }
198+ }
199+ }
0 commit comments