Skip to content

Commit 798f3f3

Browse files
committed
sprint3
1 parent 419d53b commit 798f3f3

2 files changed

Lines changed: 278 additions & 0 deletions

File tree

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// https://contest.yandex.ru/contest/23815/run-report/159759692/
2+
3+
public class BrokenArray {
4+
5+
/*
6+
* Принцип работы алгоритма:
7+
* Используем модифицированный бинарный поиск.
8+
* На каждом шаге рассматриваем середину отрезка [left, right].
9+
* Хотя массив "сломанный" (циклически сдвинутый), хотя бы одна из половин
10+
* [left, mid] или [mid, right] обязательно отсортирована по возрастанию.
11+
* Определяем, какая именно половина отсортирована, и проверяем, может ли
12+
* искомый элемент k лежать внутри неё. Если да — продолжаем поиск в этой
13+
* половине, иначе — в другой.
14+
*
15+
* Почему алгоритм корректен:
16+
* 1) В массиве все элементы уникальны, значит для любой середины можно
17+
* однозначно понять, какая половина отсортирована.
18+
* 2) Если левая половина отсортирована и k лежит в её диапазоне значений,
19+
* то k может находиться только в ней; правую половину можно отбросить.
20+
* Аналогично для правой половины.
21+
* 3) На каждом шаге размер рассматриваемого отрезка строго уменьшается,
22+
* поэтому алгоритм завершится.
23+
* 4) Если k есть в массиве, мы не отбросим отрезок, где он расположен,
24+
* значит рано или поздно попадём в его индекс. Если k нет, указатели
25+
* пересекутся, и мы корректно вернём -1.
26+
*
27+
* Временная сложность: O(log n), где n — количество элементов в массиве
28+
* (n = arr.length), так как на каждом шаге отбрасывается примерно
29+
* половина массива.
30+
* Пространственная сложность: O(1).
31+
*/
32+
public static int brokenSearch(int[] arr, int k) {
33+
int left = 0;
34+
int right = arr.length - 1;
35+
36+
while (left <= right) {
37+
int mid = left + (right - left) / 2;
38+
39+
if (arr[mid] == k) {
40+
return mid;
41+
}
42+
43+
if (arr[left] <= arr[mid]) {
44+
if (arr[left] <= k && k < arr[mid]) {
45+
right = mid - 1;
46+
} else {
47+
left = mid + 1;
48+
}
49+
} else {
50+
if (arr[mid] < k && k <= arr[right]) {
51+
left = mid + 1;
52+
} else {
53+
right = mid - 1;
54+
}
55+
}
56+
}
57+
58+
return -1;
59+
}
60+
61+
private static void test() {
62+
int[] arr1 = {19, 21, 100, 101, 1, 4, 5, 7, 12};
63+
assert 6 == brokenSearch(arr1, 5);
64+
65+
int[] arr2 = {5, 1};
66+
assert 1 == brokenSearch(arr2, 1);
67+
68+
int[] arr3 = {1, 2, 3, 4, 5, 6};
69+
assert 3 == brokenSearch(arr3, 4);
70+
71+
int[] arr4 = {4, 5, 6, 7, 0, 1, 2};
72+
assert 4 == brokenSearch(arr4, 0);
73+
assert -1 == brokenSearch(arr4, 3);
74+
75+
int[] arr5 = {1};
76+
assert 0 == brokenSearch(arr5, 1);
77+
assert -1 == brokenSearch(arr5, 2);
78+
}
79+
}
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
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\ntimofey\nalla\ngosha\nrita\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

Comments
 (0)