Compare commits

..

16 Commits

Author SHA1 Message Date
prixod
dfbb01757c update test endpoint 2025-11-05 21:43:24 +04:00
prixod
c926699a46 package parsing update 2025-11-04 23:45:59 +04:00
prixod
ffd0de446d update isolate integrity 2025-11-04 23:36:31 +04:00
prixod
44cb179cf5 update isolate integrity 2025-11-04 23:16:13 +04:00
prixod
b61eac05a2 add isolate integrity 2025-11-04 23:07:12 +04:00
prixod
48c2b4dafd docker isolation update 2025-11-04 20:22:51 +04:00
prixod
cb346db783 Merge remote-tracking branch 'origin/roman' into dev 2025-11-04 17:23:30 +04:00
bf7bd0ad6b Improves package download and caching
All checks were successful
Build and Push Docker Images / build (src/LiquidCode.Tester.Gateway/Dockerfile, git.nullptr.top/liquidcode/liquidcode-tester-gateway-roman, gateway) (push) Successful in 53s
Build and Push Docker Images / build (src/LiquidCode.Tester.Worker/Dockerfile, git.nullptr.top/liquidcode/liquidcode-tester-worker-roman, worker) (push) Successful in 50s
Adds package caching to reduce download frequency.

Introduces a `PackageDownloadService` with memory caching to store downloaded packages,
identified by mission ID, for reuse. Uses concurrent locks to prevent race conditions during download.

Modifies the worker client service to optionally delete the package after sending,
allowing cached packages to be retained.
2025-11-02 20:05:50 +03:00
b95d94d796 параллельные джобы
All checks were successful
Build and Push Docker Images / build (src/LiquidCode.Tester.Gateway/Dockerfile, git.nullptr.top/liquidcode/liquidcode-tester-gateway-roman, gateway) (push) Successful in 48s
Build and Push Docker Images / build (src/LiquidCode.Tester.Worker/Dockerfile, git.nullptr.top/liquidcode/liquidcode-tester-worker-roman, worker) (push) Successful in 4m26s
2025-11-02 19:34:01 +03:00
e154890897 Штуки
Some checks failed
Build and Push Docker Images / build (src/LiquidCode.Tester.Gateway/Dockerfile, git.nullptr.top/liquidcode/liquidcode-tester-gateway-roman, gateway) (push) Successful in 1m12s
Build and Push Docker Images / build (src/LiquidCode.Tester.Worker/Dockerfile, git.nullptr.top/liquidcode/liquidcode-tester-worker-roman, worker) (push) Has been cancelled
2025-11-02 19:31:34 +03:00
prixod
66bcf756fe Merge branch 'master' into dev 2025-11-02 19:35:01 +04:00
prixod
1e77503580 Merge remote-tracking branch 'origin/dev' into dev 2025-11-02 19:34:44 +04:00
50a94ae2be swagger enable always
All checks were successful
Build and Push Docker Images / build (src/LiquidCode.Tester.Gateway/Dockerfile, git.nullptr.top/liquidcode/liquidcode-tester-gateway, gateway) (push) Successful in 28s
Build and Push Docker Images / build (src/LiquidCode.Tester.Worker/Dockerfile, git.nullptr.top/liquidcode/liquidcode-tester-worker, worker) (push) Successful in 27s
2025-11-02 15:35:28 +03:00
36013090c1 Merge pull request 'update polygon package parsing & testing' (#1) from dev into master
All checks were successful
Build and Push Docker Images / build (src/LiquidCode.Tester.Gateway/Dockerfile, git.nullptr.top/liquidcode/liquidcode-tester-gateway, gateway) (push) Successful in 47s
Build and Push Docker Images / build (src/LiquidCode.Tester.Worker/Dockerfile, git.nullptr.top/liquidcode/liquidcode-tester-worker, worker) (push) Successful in 1m13s
Reviewed-on: #1
2025-11-02 11:20:08 +00:00
prixod
06c6d06186 update polygon package parsing & testing 2025-10-28 22:03:50 +04:00
prixod
69829569bb update polygon package parsing & testing 2025-10-28 22:01:35 +04:00
138 changed files with 16424 additions and 222 deletions

View File

@@ -2,7 +2,7 @@ name: Build and Push Docker Images
on:
push:
branches: [ master ]
branches: [ roman ]
env:
REGISTRY: git.nullptr.top
@@ -11,15 +11,16 @@ jobs:
build:
runs-on: ubuntu-latest
strategy:
max-parallel: 2
matrix:
service: [ gateway, worker ]
include:
- service: gateway
dockerfile: src/LiquidCode.Tester.Gateway/Dockerfile
image: git.nullptr.top/liquidcode/liquidcode-tester-gateway
image: git.nullptr.top/liquidcode/liquidcode-tester-gateway-roman
- service: worker
dockerfile: src/LiquidCode.Tester.Worker/Dockerfile
image: git.nullptr.top/liquidcode/liquidcode-tester-worker
image: git.nullptr.top/liquidcode/liquidcode-tester-worker-roman
steps:
- name: Checkout repository
uses: actions/checkout@v4

311
ISOLATE_INTEGRATION.md Normal file
View File

@@ -0,0 +1,311 @@
# Isolate Sandbox Integration
## Обзор
Интеграция Isolate sandbox обеспечивает безопасное выполнение пользовательского кода с изоляцией на уровне ядра Linux.
## Что было сделано
### 1. Docker Security Hardening
**compose.yaml:**
- ✅ Gateway: `cap_drop: ALL`, `no-new-privileges:true`
- ✅ Worker: `cap_drop: ALL` + минимальные capabilities (`SYS_ADMIN`, `SETUID`, `SETGID`)
- ✅ Worker: `tmpfs` для `/tmp` (4GB)
- ✅ Worker: `ulimits` (nproc: 1024, nofile: 2048)
- ✅ AppArmor profile
### 2. Worker Dockerfile
**Установлено:**
- ✅ Isolate sandbox (с libcap-dev, libsystemd-dev)
- ✅ Unprivileged user `workeruser` (uid: 1001)
- ✅ Конфигурация isolate (`/usr/local/etc/isolate`)
**Структура:**
```
/var/local/lib/isolate/ - Isolate box root
/app/ - Worker приложение (chown workeruser)
/tmp/testing/ - Temp directory (chown workeruser)
```
### 3. Новые сервисы
**`IsolateService`** - Основной сервис для работы с Isolate:
- `InitBoxAsync(boxId)` - Инициализация sandbox
- `RunAsync(options)` - Выполнение программы
- `CleanupBoxAsync(boxId)` - Очистка sandbox
- Парсинг metadata (CPU time, memory, context switches)
**`IsolateBoxPool`** - Управление параллельными box'ами:
- Пул из N box IDs (конфигурируется)
- Thread-safe acquire/release
- Автоматическое ожидание при занятости всех box'ов
**`CppExecutionServiceIsolate`** - Реализация IExecutionService с Isolate:
- Копирование executable в box
- Выполнение с ограничениями (CPU, memory, processes)
- Mapping результатов Isolate → ExecutionResult
### 4. Конфигурация
**appsettings.json:**
```json
{
"Isolate": {
"Enabled": true,
"MaxBoxes": 100
}
}
```
**Environment переменные (compose.yaml):**
```yaml
environment:
- Isolate__Enabled=true
- Isolate__MaxBoxes=100
```
## Что защищает Isolate
| Угроза | Без Isolate | С Isolate |
|--------|-------------|-----------|
| Fork bomb | ❌ Убьёт контейнер | ✅ БЛОК (process limit) |
| Network attack | ❌ Полный доступ | ✅ БЛОК (no network) |
| File access | ❌ Видит весь контейнер | ✅ БЛОК (mount namespace) |
| Memory bomb | ⚠️ Неточно (PeakWorkingSet64) | ✅ ТОЧНО (cgroups) |
| CPU bomb | ⚠️ Wall time | ✅ CPU time (справедливо) |
| Syscall abuse | ❌ Любые syscalls | ✅ ФИЛЬТР (seccomp) |
## Архитектура безопасности
```
┌─────────────────────────────────────────────┐
│ HOST OS (Linux) │
│ ┌───────────────────────────────────────┐ │
│ │ Docker Container (Worker) │ │
│ │ • cap_drop: ALL │ │
│ │ • no-new-privileges │ │
│ │ • AppArmor │ │
│ │ │ │
│ │ ┌─────────────────────────────────┐ │ │
│ │ │ Worker Process (uid 1001) │ │ │
│ │ │ │ │ │
│ │ │ ┌───────────────────────────┐ │ │ │
│ │ │ │ Isolate Box │ │ │ │
│ │ │ │ • PID namespace │ │ │ │
│ │ │ │ • Network isolation │ │ │ │
│ │ │ │ • Mount namespace │ │ │ │
│ │ │ │ • cgroups (CPU, mem) │ │ │ │
│ │ │ │ • seccomp-bpf │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ USER CODE RUNS HERE │ │ │ │
│ │ │ └───────────────────────────┘ │ │ │
│ │ └─────────────────────────────────┘ │ │
│ └───────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
```
## Тестирование
### Запуск с Isolate
```bash
# 1. Rebuild контейнеров
docker-compose down
docker-compose build --no-cache worker
docker-compose up
# 2. Проверка установки Isolate
docker exec liquidcode-tester-worker isolate --version
# 3. Проверка прав
docker exec liquidcode-tester-worker whoami # должно быть: workeruser
# 4. Проверка box директории
docker exec liquidcode-tester-worker ls -la /var/local/lib/isolate
```
### Тестовые сценарии
#### 1. Простая программа (C++)
```bash
curl -X POST http://localhost:8081/api/test \
-F "id=1" \
-F "missionId=100" \
-F "language=c++" \
-F "sourceCode=#include <iostream>
int main() { std::cout << \"Hello World\"; }" \
-F "callbackUrl=http://localhost/callback" \
-F "package=@test_package.zip"
```
#### 2. Fork bomb (должен быть ЗАБЛОКИРОВАН)
```cpp
#include <unistd.h>
int main() {
while(1) fork();
}
```
#### 3. Network attack (должен быть ЗАБЛОКИРОВАН)
```cpp
#include <iostream>
#include <cstdlib>
int main() {
system("curl http://evil.com");
}
```
#### 4. Memory bomb (должен быть ОСТАНОВЛЕН)
```cpp
#include <vector>
int main() {
std::vector<int> v;
while(1) v.push_back(1);
}
```
#### 5. Time limit
```cpp
#include <unistd.h>
int main() {
sleep(10);
}
```
### Проверка логов
```bash
# Проверка использования Isolate
docker logs liquidcode-tester-worker 2>&1 | grep "Isolate"
# Проверка box acquire/release
docker logs liquidcode-tester-worker 2>&1 | grep "box"
# Проверка метрик
docker logs liquidcode-tester-worker 2>&1 | grep "Isolate stats"
```
### Проверка безопасности
```bash
# 1. Проверка capabilities контейнера
docker inspect liquidcode-tester-worker | jq '.[0].HostConfig.CapDrop'
docker inspect liquidcode-tester-worker | jq '.[0].HostConfig.CapAdd'
# 2. Проверка security_opt
docker inspect liquidcode-tester-worker | jq '.[0].HostConfig.SecurityOpt'
# 3. Проверка ulimits
docker inspect liquidcode-tester-worker | jq '.[0].HostConfig.Ulimits'
```
## Производительность
### Overhead на один запуск:
| Операция | Время |
|----------|-------|
| Init box | ~10-15ms |
| Run program | 0ms (в пределах погрешности) |
| Cleanup | ~5-10ms |
| **Total overhead** | **~25ms** |
### Для задачи с 100 тестами (1s TL каждый):
- Overhead: 25ms × 100 = 2.5s
- Типичное время: 100s
- Увеличение: **+2.5%** (незначительно!)
### Pool statistics:
```bash
# Monitoring через API endpoint (TODO)
curl http://localhost:8081/api/monitoring/isolate-pool
```
## Отключение Isolate
Для отключения Isolate (вернуться к старому поведению):
**appsettings.json:**
```json
{
"Isolate": {
"Enabled": false
}
}
```
Или через environment:
```yaml
environment:
- Isolate__Enabled=false
```
## Следующие шаги
### Фаза 2: Full execution integration (неделя 2)
- [ ] Интегрировать Isolate в JavaExecutionService
- [ ] Интегрировать Isolate в KotlinExecutionService
- [ ] Интегрировать Isolate в CSharpExecutionService
- [ ] Интегрировать Isolate в PythonExecutionService
### Фаза 3: Compilation + Checker (неделя 3)
- [ ] Изолировать компиляцию (CppCompilationService и др.)
- [ ] Изолировать checker (CheckerService)
- [ ] Тестирование с реальными Polygon пакетами
### Улучшения
- [ ] Monitoring endpoint для статистики box pool
- [ ] Graceful degradation при недоступности Isolate
- [ ] Кэширование executable в box (для checker)
- [ ] Custom AppArmor profile (advanced)
- [ ] Metrics (Prometheus)
## Известные ограничения
1. **Только Linux** - Isolate работает только на Linux kernel
2. **CAP_SYS_ADMIN** - Worker контейнер требует повышенных прав
3. **Box pool limit** - Максимум 100 параллельных заданий (конфигурируется)
4. **Workeruser permissions** - Некоторые операции могут требовать root
## Troubleshooting
### Isolate not found
```bash
# Проверка установки
docker exec liquidcode-tester-worker which isolate
docker exec liquidcode-tester-worker isolate --version
```
### Permission denied
```bash
# Проверка владельца директорий
docker exec liquidcode-tester-worker ls -la /var/local/lib/isolate
docker exec liquidcode-tester-worker ls -la /app
```
### Box initialization failed
```bash
# Проверка capabilities
docker inspect liquidcode-tester-worker | jq '.[0].HostConfig.CapAdd'
# Должны быть: SYS_ADMIN, SETUID, SETGID
```
### Cgroups not working
```bash
# Проверка cgroup v2
docker exec liquidcode-tester-worker ls -la /sys/fs/cgroup
# Проверка конфигурации isolate
docker exec liquidcode-tester-worker cat /usr/local/etc/isolate
```
## Ссылки
- [Isolate GitHub](https://github.com/ioi/isolate)
- [Isolate Documentation](https://github.com/ioi/isolate/blob/master/isolate.1.txt)
- [CMS (Contest Management System)](https://github.com/cms-dev/cms)
- [Docker Security Best Practices](https://docs.docker.com/engine/security/)

View File

@@ -0,0 +1,579 @@
# Структура пакета Polygon
## 📦 Типичная структура Polygon пакета
```
problem-name.zip
├── problem.xml ← Главный дескриптор задачи
├── tests/ ← Тесты для проверки решений
│ ├── 01 ← Входные данные (без расширения!)
│ ├── 01.a ← Ответы (могут отсутствовать)
│ ├── 02
│ ├── 02.a
│ └── ...
├── files/ ← Вспомогательные файлы
│ ├── testlib.h ← Библиотека для checker/validator/generator
│ ├── olymp.sty ← LaTeX стиль для statements
│ ├── problem.tex ← Шаблон условия
│ ├── statements.ftl ← FreeMarker шаблон
│ │
│ ├── tests/ ← Тесты для checker/validator
│ │ ├── checker-tests/
│ │ │ ├── 01
│ │ │ ├── 01.a
│ │ │ └── 01.o ← Ожидаемый output
│ │ │
│ │ └── validator-tests/
│ │ ├── 01
│ │ ├── 02
│ │ └── ...
│ │
│ ├── g.cpp ← Generator (генератор тестов)
│ ├── g.exe
│ ├── v.cpp ← Validator (валидатор входных данных)
│ ├── v.exe
│ ├── check.cpp ← Checker (проверка ответа)
│ ├── check.exe
│ ├── interactor.cpp ← Interactor (для интерактивных задач)
│ ├── interactor.exe
│ │
│ └── [resource files] ← Дополнительные ресурсы для решений
│ ├── aplusb.h ← Header для grader-задач
│ ├── grader.cpp ← Grader для компиляции с решением
│ └── main.py ← Python wrapper для grader
├── solutions/ ← Эталонные решения
│ ├── sol.cpp ← Главное (main) решение
│ ├── sol.exe
│ ├── sol.py
│ ├── sol.java
│ │
│ ├── sol-accepted-1.cpp ← Дополнительные AC решения
│ ├── sol-wa.cpp ← Wrong Answer решения (для теста)
│ ├── sol-tl.cpp ← Time Limit решения
│ ├── sol-ml.cpp ← Memory Limit решения
│ └── ...
├── statements/ ← Условия задачи
│ ├── english/
│ │ ├── problem.tex ← Исходник условия (LaTeX)
│ │ ├── problem-properties.json
│ │ ├── tutorial.tex ← Разбор задачи
│ │ ├── example.01 ← Примеры из условия (input)
│ │ └── example.01.a ← Примеры из условия (output)
│ │
│ ├── russian/
│ │ └── ...
│ │
│ ├── .html/ ← Сгенерированные HTML
│ │ ├── english/
│ │ │ ├── problem.html
│ │ │ ├── tutorial.html
│ │ │ └── problem-statement.css
│ │ └── russian/
│ │
│ └── .pdf/ ← Сгенерированные PDF
│ ├── english/
│ │ ├── problem.pdf
│ │ └── tutorial.pdf
│ └── russian/
├── statement-sections/ ← Секции условия (модульно)
│ ├── english/
│ │ ├── legend.tex
│ │ ├── input.tex
│ │ ├── output.tex
│ │ ├── notes.tex
│ │ ├── scoring.tex
│ │ └── examples/
│ └── russian/
├── materials/ ← Материалы для участников
│ ├── grader-cpp.zip ← Grader для C++
│ ├── grader-py.zip ← Grader для Python
│ └── ...
├── scripts/ ← Скрипты для работы с пакетом
│ ├── gen-answer.sh
│ ├── gen-input-via-files.sh
│ ├── run-validator-tests.sh
│ └── ...
├── check.cpp ← Checker в корне (копия)
├── check.exe
├── doall.sh ← Скрипт сборки всего
├── doall.bat
├── wipe.sh ← Скрипт очистки
├── wipe.bat
└── tags ← Теги задачи (metadata)
```
---
## 📄 Основные файлы и их назначение
### 1. **problem.xml** (обязательный)
Центральный дескриптор задачи:
```xml
<?xml version="1.0" encoding="utf-8"?>
<problem revision="17" short-name="example-problem" url="...">
<names>
<name language="english" value="Problem Title"/>
</names>
<judging>
<testset name="tests">
<time-limit>2000</time-limit> <!-- мс -->
<memory-limit>268435456</memory-limit> <!-- байты = 256 MB -->
<test-count>51</test-count>
<input-path-pattern>tests/%02d</input-path-pattern>
<answer-path-pattern>tests/%02d.a</answer-path-pattern>
<tests>
<test method="manual" sample="true"/> <!-- ручной, в примерах -->
<test cmd="gen 100" method="generated"/> <!-- сгенерированный -->
<test cmd="gen 1000" method="generated"/>
...
</tests>
</testset>
</judging>
<assets>
<checker name="std::ncmp.cpp" type="testlib">
<source path="files/check.cpp" type="cpp.g++17"/>
<binary path="check.exe" type="exe.win32"/>
</checker>
<validators>
<validator>
<source path="files/v.cpp" type="cpp.g++17"/>
<binary path="files/v.exe" type="exe.win32"/>
</validator>
</validators>
<solutions>
<solution tag="main">
<source path="solutions/sol.cpp" type="cpp.g++17"/>
<binary path="solutions/sol.exe" type="exe.win32"/>
</solution>
<solution tag="accepted">
<source path="solutions/sol.py" type="python.3"/>
</solution>
<solution tag="wrong-answer">
<source path="solutions/sol-wa.cpp" type="cpp.g++17"/>
</solution>
</solutions>
</assets>
</problem>
```
---
### 2. **testlib.h** (стандартная библиотека)
Библиотека от MikeMirzayanov для написания:
- **Checkers** - проверка правильности ответа
- **Validators** - проверка корректности входных данных
- **Generators** - генерация тестов
- **Interactors** - интерактивное взаимодействие
**Основные функции:**
```cpp
#include "testlib.h"
// Checker
int main(int argc, char* argv[]) {
registerTestlibCmd(argc, argv);
int jans = ans.readInt(); // Правильный ответ
int pans = ouf.readInt(); // Ответ участника
if (jans == pans)
quitf(_ok, "Correct");
else
quitf(_wa, "Wrong answer: %d instead of %d", pans, jans);
}
// Validator
int main(int argc, char* argv[]) {
registerValidation(argc, argv);
int n = inf.readInt(1, 100000, "n");
inf.readEoln();
inf.readEof();
}
// Generator
int main(int argc, char* argv[]) {
registerGen(argc, argv, 1);
int n = opt<int>("n");
println(n);
for (int i = 0; i < n; i++)
println(rnd.next(1, 1000000));
}
```
---
### 3. **Тесты (tests/)**
**Формат:**
```
tests/01 ← Входные данные (plain text, без расширения)
tests/01.a ← Ответ (answer file)
```
**Пример:**
```
# tests/01 (input)
2 3
# tests/01.a (answer)
5
```
**Метаданные из problem.xml:**
```xml
<tests>
<test method="manual" sample="true"/> <!-- tests/01 - вручную, в примерах -->
<test cmd="gen 10 5" method="generated"/> <!-- tests/02 - сгенерирован -->
<test cmd="gen 100 50" method="generated"/> <!-- tests/03 -->
</tests>
```
---
### 4. **Generator (g.cpp)**
Программа для генерации тестов:
```cpp
#include "testlib.h"
#include <iostream>
int main(int argc, char* argv[]) {
registerGen(argc, argv, 1);
int n = opt<int>(1); // Первый аргумент
int maxVal = opt<int>(2); // Второй аргумент
std::cout << n << std::endl;
for (int i = 0; i < n; i++) {
std::cout << rnd.next(1, maxVal);
if (i + 1 < n) std::cout << " ";
}
std::cout << std::endl;
return 0;
}
```
**Использование:**
```bash
# В problem.xml указано:
<test cmd="gen 1000 10000" method="generated"/>
# Polygon запускает:
g.exe 1000 10000 > tests/05
```
---
### 5. **Checker (check.cpp)**
Программа для проверки корректности ответа.
**Типы checkers:**
#### **A. Стандартные (встроенные в testlib.h):**
```cpp
std::ncmp.cpp // Сравнение одного целого числа
std::fcmp.cpp // Сравнение одного float с точностью
std::wcmp.cpp // Сравнение по словам (tokens)
std::lcmp.cpp // Построчное сравнение
std::nyesno.cpp // Проверка YES/NO
```
#### **B. Custom checker:**
```cpp
#include "testlib.h"
int main(int argc, char* argv[]) {
registerTestlibCmd(argc, argv);
// inf - входной файл (input)
// ouf - output участника (output user file)
// ans - правильный ответ (answer)
int n = inf.readInt();
std::vector<int> jans(n);
for (int i = 0; i < n; i++)
jans[i] = ans.readInt();
std::vector<int> pans(n);
for (int i = 0; i < n; i++)
pans[i] = ouf.readInt();
// Проверка: порядок не важен (множества равны)
std::sort(jans.begin(), jans.end());
std::sort(pans.begin(), pans.end());
if (jans == pans)
quitf(_ok, "Correct");
else
quitf(_wa, "Wrong answer");
}
```
**Exit codes:**
- `0` - OK (правильный ответ) ✅
- `1` - WA (неправильный ответ) ❌
- `2` - PE (presentation error)
- `3` - FAIL (ошибка в самом чекере)
- `7` - Partial (частичный балл, для IOI-style)
---
### 6. **Validator (v.cpp)**
Проверяет корректность входных данных:
```cpp
#include "testlib.h"
int main(int argc, char* argv[]) {
registerValidation(argc, argv);
// Проверка формата входных данных
int n = inf.readInt(1, 100000, "n"); // 1 ≤ n ≤ 100000
inf.readEoln(); // Конец строки
for (int i = 0; i < n; i++) {
inf.readInt(1, 1000000000, "a[i]");
if (i + 1 < n) inf.readSpace();
else inf.readEoln();
}
inf.readEof(); // Конец файла
return 0;
}
```
**Назначение:**
- Проверка ограничений (1 ≤ n ≤ 10⁶)
- Проверка формата (пробелы, переводы строк)
- Валидация структуры (дерево, граф и т.д.)
---
### 7. **Interactor (для интерактивных задач)**
Посредник между решением и тестирующей системой:
```cpp
#include "testlib.h"
int main(int argc, char* argv[]) {
registerInteraction(argc, argv);
int n = inf.readInt(); // Загаданное число
int queries = 0;
while (queries < 20) {
int guess = ouf.readInt(1, 1000000); // Запрос участника
queries++;
if (guess == n) {
tout << "YES" << endl;
quitf(_ok, "Found in %d queries", queries);
} else if (guess < n) {
tout << ">" << endl; // Больше
} else {
tout << "<" << endl; // Меньше
}
}
quitf(_wa, "Too many queries");
}
```
**Streams в interactor:**
- `inf` - входной файл (input)
- `ouf` - output участника (чтение запросов)
- `tout` - передача данных участнику (ответы на запросы)
- `ans` - правильный ответ (не используется в интерактивных)
---
### 8. **Solutions (эталонные решения)**
**Типы решений:**
```xml
<solution tag="main"> <!-- Главное решение (генерирует .a файлы) -->
<solution tag="accepted"> <!-- Дополнительные AC решения -->
<solution tag="wrong-answer"> <!-- WA (для теста checker'а) -->
<solution tag="time-limit-exceeded"> <!-- TL -->
<solution tag="memory-limit-exceeded"> <!-- ML -->
<solution tag="rejected"> <!-- Другие RE/PE -->
```
**Назначение:**
- `main` - используется для генерации answer files
- `accepted` - проверка, что задача решаема разными способами
- `wrong-answer` - тестирование checker'а
- `time-limit-exceeded` - проверка TL
---
### 9. **Grader-задачи (специальный тип)**
Участник пишет функцию, а не всю программу.
**Структура:**
```
files/
├── aplusb.h ← Header с сигнатурой функции
├── grader.cpp ← Main + вызов функции участника
└── main.py ← Python wrapper
solutions/
└── sol.cpp ← Реализация функции (не main!)
```
**Пример:**
```cpp
// aplusb.h
int sum(int a, int b);
// grader.cpp
#include "aplusb.h"
#include <iostream>
int main() {
int a, b;
std::cin >> a >> b;
std::cout << sum(a, b) << std::endl;
return 0;
}
// sol.cpp (решение участника)
#include "aplusb.h"
int sum(int a, int b) {
return a + b;
}
```
---
## 📊 Статистика по примерам пакетов
### **a-plus-b-graders-7.zip:**
```
Размер: 2.4 MB
Файлов: ~50
Структура:
✅ problem.xml
✅ tests/ (8 тестов: 01-08, без .a файлов)
✅ files/testlib.h
✅ files/aplusb.h (grader header)
✅ files/grader.cpp
✅ files/g.cpp, g.exe (generator)
✅ files/v.cpp, v.exe (validator)
✅ check.cpp, check.exe (ncmp - числовой checker)
✅ solutions/sol.cpp (main)
✅ solutions/sol.py (accepted)
✅ statements/english/ (условие)
```
### **example-interactive-binary-search-26.zip:**
```
Размер: 10.7 MB
Файлов: ~100+
Структура:
✅ problem.xml
✅ tests/ (21 тест: 01-21, без .a файлов)
✅ files/testlib.h
✅ files/interactor.cpp, interactor.exe ← ИНТЕРАКТИВНАЯ!
✅ files/gen.cpp, gen.exe
✅ files/val.cpp, val.exe
✅ check.cpp, check.exe
✅ solutions/ (16 решений: main, ac, wa, tl, ml, pe, ...)
✅ statements/english/ + russian/
```
### **exam-queue-17.zip:**
```
Размер: 6.6 MB
Файлов: ~80
Структура:
✅ problem.xml
✅ tests/ (51 тест: 01-51, без .a файлов)
✅ files/testlib.h
✅ files/gen.cpp, gen.exe
✅ files/val.cpp, val.exe
✅ check.cpp, check.exe
✅ solutions/ (множество решений)
✅ statements/russian/ (только русское условие)
```
---
## 💡 Ключевые выводы
### **Обязательные компоненты:**
1.`problem.xml` - дескриптор
2.`tests/` - тесты
3.`files/testlib.h` - библиотека
4.`solutions/` - хотя бы одно main решение
### **Опциональные (но часто присутствуют):**
- `check.cpp` - custom checker (иначе используется wcmp)
- `v.cpp` - validator
- `g.cpp` - generator
- `interactor.cpp` - для интерактивных задач
- `statements/` - условия на разных языках
- `*.a` файлы - ответы (генерируются из main solution)
### **Особенности формата:**
- Входные файлы **БЕЗ расширения** (01, 02, не 01.in!)
- Ответы с расширением `.a` (01.a, 02.a)
- testlib.h - единая библиотека для всего
- problem.xml - полное описание всего пакета
---
## 🔗 Полезные ссылки
- **Polygon:** https://polygon.codeforces.com/
- **testlib.h GitHub:** https://github.com/MikeMirzayanov/testlib
- **Документация testlib:** https://codeforces.com/testlib
- **Tutorial по Polygon:** https://codeforces.com/blog/entry/101072
---
## 🎯 Поддержка в LiquidCode.Tester
Наша система **полностью поддерживает**:
- ✅ Парсинг problem.xml
- ✅ Тесты в формате tests/01, tests/01.a
- ✅ Автоматическую генерацию answer файлов из main solution
- ✅ Компиляцию и запуск custom checkers (testlib-based)
- ✅ Определение лимитов времени/памяти из problem.xml
- ✅ Поддержку всех основных языков (C++, Java, Python, C#, Kotlin)
**В разработке:**
- ⏳ Поддержка interactor для интерактивных задач
- ⏳ Поддержка grader-задач
- ⏳ Запуск validator для проверки входных данных

View File

@@ -18,6 +18,11 @@
- liquidcode-network
depends_on:
- worker
# Security hardening for Gateway
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
worker:
image: liquidcode-tester-worker:latest
@@ -31,14 +36,23 @@
- ASPNETCORE_ENVIRONMENT=Development
networks:
- liquidcode-network
# For better isolation in production, consider:
# security_opt:
# - no-new-privileges:true
# cap_drop:
# - ALL
# cap_add:
# - SETUID
# - SETGID
# Security hardening for Worker
security_opt:
- no-new-privileges:true
- apparmor=docker-default
cap_drop:
- ALL
cap_add:
- SYS_ADMIN # Required for Isolate namespaces
- SETUID # Required for Isolate to change user context
- SETGID # Required for Isolate to change group context
# Temporary filesystem for compilation and testing
tmpfs:
- /tmp:exec,size=4G
# Resource limits to prevent DoS
ulimits:
nproc: 1024 # Max processes
nofile: 2048 # Max open files
networks:
liquidcode-network:

57
exam-queue-17/check.cpp Normal file
View File

@@ -0,0 +1,57 @@
#include "testlib.h"
#include <sstream>
using namespace std;
int main(int argc, char * argv[])
{
setName("compare ordered sequences of signed int%d numbers", 8 * int(sizeof(long long)));
registerTestlibCmd(argc, argv);
int n = 0;
string firstElems;
while (!ans.seekEof() && !ouf.seekEof())
{
n++;
long long j = ans.readLong();
long long p = ouf.readLong();
if (j != p)
quitf(_wa, "%d%s numbers differ - expected: '%s', found: '%s'", n, englishEnding(n).c_str(), vtos(j).c_str(), vtos(p).c_str());
else
if (n <= 5)
{
if (firstElems.length() > 0)
firstElems += " ";
firstElems += vtos(j);
}
}
int extraInAnsCount = 0;
while (!ans.seekEof())
{
ans.readLong();
extraInAnsCount++;
}
int extraInOufCount = 0;
while (!ouf.seekEof())
{
ouf.readLong();
extraInOufCount++;
}
if (extraInAnsCount > 0)
quitf(_wa, "Answer contains longer sequence [length = %d], but output contains %d elements", n + extraInAnsCount, n);
if (extraInOufCount > 0)
quitf(_wa, "Output contains longer sequence [length = %d], but answer contains %d elements", n + extraInOufCount, n);
if (n <= 5)
quitf(_ok, "%d number(s): \"%s\"", n, compress(firstElems).c_str());
else
quitf(_ok, "%d numbers", n);
}

BIN
exam-queue-17/check.exe Normal file

Binary file not shown.

108
exam-queue-17/doall.bat Normal file
View File

@@ -0,0 +1,108 @@
rem *** validation ***
call scripts\run-validator-tests.bat
call scripts\run-checker-tests.bat
rem *** tests ***
md tests
call scripts\gen-input-via-stdout.bat "files\gen.exe 1 5 10 5 10 1 100" "tests\02" 2
call scripts\gen-input-via-stdout.bat "files\gen.exe 2 5 10 5 10 1 100" "tests\03" 3
call scripts\gen-input-via-stdout.bat "files\gen.exe 3 5 10 5 10 1 100" "tests\04" 4
call scripts\gen-input-via-stdout.bat "files\gen.exe 4 5 10 5 10 1 100" "tests\05" 5
call scripts\gen-input-via-stdout.bat "files\gen.exe 5 5 10 5 10 1 100" "tests\06" 6
call scripts\gen-input-via-stdout.bat "files\gen.exe 1 50 100 500 1000 1 1000000" "tests\07" 7
call scripts\gen-input-via-stdout.bat "files\gen.exe 2 50 100 500 1000 1 1000000" "tests\08" 8
call scripts\gen-input-via-stdout.bat "files\gen.exe 3 50 100 500 1000 1 1000000" "tests\09" 9
call scripts\gen-input-via-stdout.bat "files\gen.exe 4 50 100 500 1000 1 1000000" "tests\10" 10
call scripts\gen-input-via-stdout.bat "files\gen.exe 5 50 100 500 1000 1 1000000" "tests\11" 11
call scripts\gen-input-via-stdout.bat "files\gen.exe 1 50000 100000 50000 100000 1 1000000000" "tests\12" 12
call scripts\gen-input-via-stdout.bat "files\gen.exe 2 50000 100000 50000 100000 1 1000000000" "tests\13" 13
call scripts\gen-input-via-stdout.bat "files\gen.exe 3 50000 100000 50000 100000 1 1000000000" "tests\14" 14
call scripts\gen-input-via-stdout.bat "files\gen.exe 4 50000 100000 50000 100000 1 1000000000" "tests\15" 15
call scripts\gen-input-via-stdout.bat "files\gen.exe 5 50000 100000 50000 100000 1 1000000000" "tests\16" 16
call scripts\gen-input-via-stdout.bat "files\gen.exe 6 50000 100000 50000 100000 1 1000000000" "tests\17" 17
call scripts\gen-input-via-stdout.bat "files\gen.exe 7 50000 100000 50000 100000 1 1000000000" "tests\18" 18
call scripts\gen-input-via-stdout.bat "files\gen.exe 8 50000 100000 50000 100000 1 1000000000" "tests\19" 19
call scripts\gen-input-via-stdout.bat "files\gen.exe 9 50000 100000 50000 100000 1 1000000000" "tests\20" 20
call scripts\gen-input-via-stdout.bat "files\gen.exe 10 50000 100000 50000 100000 1 1000000000" "tests\21" 21
call scripts\gen-input-via-stdout.bat "files\gen.exe 1 100000 100000 100000 100000 1 1000000000" "tests\22" 22
call scripts\gen-input-via-stdout.bat "files\gen.exe 2 100000 100000 100000 100000 1 1000000000" "tests\23" 23
call scripts\gen-input-via-stdout.bat "files\gen.exe 3 100000 100000 100000 100000 1 1000000000" "tests\24" 24
call scripts\gen-input-via-stdout.bat "files\gen.exe 4 100000 100000 100000 100000 1 1000000000" "tests\25" 25
call scripts\gen-input-via-stdout.bat "files\gen.exe 5 100000 100000 100000 100000 1 1000000000" "tests\26" 26
call scripts\gen-input-via-stdout.bat "files\gen.exe 6 100000 100000 100000 100000 1 1000000000" "tests\27" 27
call scripts\gen-input-via-stdout.bat "files\gen.exe 7 100000 100000 100000 100000 1 1000000000" "tests\28" 28
call scripts\gen-input-via-stdout.bat "files\gen.exe 8 100000 100000 100000 100000 1 1000000000" "tests\29" 29
call scripts\gen-input-via-stdout.bat "files\gen.exe 9 100000 100000 100000 100000 1 1000000000" "tests\30" 30
call scripts\gen-input-via-stdout.bat "files\gen.exe 10 100000 100000 100000 100000 1 1000000000" "tests\31" 31
call scripts\gen-input-via-stdout.bat "files\gen1.exe 1 100000 100000 100000 100000 1 1000000000" "tests\32" 32
call scripts\gen-input-via-stdout.bat "files\gen1.exe 2 100000 100000 100000 100000 1 1000000000" "tests\33" 33
call scripts\gen-input-via-stdout.bat "files\gen1.exe 3 100000 100000 100000 100000 1 1000000000" "tests\34" 34
call scripts\gen-input-via-stdout.bat "files\gen1.exe 4 100000 100000 100000 100000 1 1000000000" "tests\35" 35
call scripts\gen-input-via-stdout.bat "files\gen1.exe 5 100000 100000 100000 100000 1 1000000000" "tests\36" 36
call scripts\gen-input-via-stdout.bat "files\gen2.exe 1 100000 100000 100000 100000 1 1000000000" "tests\37" 37
call scripts\gen-input-via-stdout.bat "files\gen2.exe 2 100000 100000 100000 100000 1 1000000000" "tests\38" 38
call scripts\gen-input-via-stdout.bat "files\gen2.exe 3 100000 100000 100000 100000 1 1000000000" "tests\39" 39
call scripts\gen-input-via-stdout.bat "files\gen2.exe 4 100000 100000 100000 100000 1 1000000000" "tests\40" 40
call scripts\gen-input-via-stdout.bat "files\gen2.exe 5 100000 100000 100000 100000 1 1000000000" "tests\41" 41
call scripts\gen-input-via-stdout.bat "files\print.exe 1" "tests\42" 42
call scripts\gen-input-via-stdout.bat "files\print.exe 2" "tests\43" 43
call scripts\gen-input-via-stdout.bat "files\print.exe 3" "tests\44" 44
call scripts\gen-input-via-stdout.bat "files\print.exe 4" "tests\45" 45
call scripts\gen-input-via-stdout.bat "files\print.exe 5" "tests\46" 46
call scripts\gen-input-via-stdout.bat "files\print.exe 6" "tests\47" 47
call scripts\gen-input-via-stdout.bat "files\print.exe 7" "tests\48" 48
call scripts\gen-input-via-stdout.bat "files\print.exe 8" "tests\49" 49
call scripts\gen-input-via-stdout.bat "files\print.exe 9" "tests\50" 50
call scripts\gen-input-via-stdout.bat "files\print.exe 10" "tests\51" 51
call scripts\gen-answer.bat tests\01 tests\01.a "tests" "SAMPLES"
call scripts\gen-answer.bat tests\02 tests\02.a "tests" "POINTS"
call scripts\gen-answer.bat tests\03 tests\03.a "tests" "POINTS"
call scripts\gen-answer.bat tests\04 tests\04.a "tests" "POINTS"
call scripts\gen-answer.bat tests\05 tests\05.a "tests" "POINTS"
call scripts\gen-answer.bat tests\06 tests\06.a "tests" "POINTS"
call scripts\gen-answer.bat tests\07 tests\07.a "tests" "POINTS"
call scripts\gen-answer.bat tests\08 tests\08.a "tests" "POINTS"
call scripts\gen-answer.bat tests\09 tests\09.a "tests" "POINTS"
call scripts\gen-answer.bat tests\10 tests\10.a "tests" "POINTS"
call scripts\gen-answer.bat tests\11 tests\11.a "tests" "POINTS"
call scripts\gen-answer.bat tests\12 tests\12.a "tests" "POINTS"
call scripts\gen-answer.bat tests\13 tests\13.a "tests" "POINTS"
call scripts\gen-answer.bat tests\14 tests\14.a "tests" "POINTS"
call scripts\gen-answer.bat tests\15 tests\15.a "tests" "POINTS"
call scripts\gen-answer.bat tests\16 tests\16.a "tests" "POINTS"
call scripts\gen-answer.bat tests\17 tests\17.a "tests" "POINTS"
call scripts\gen-answer.bat tests\18 tests\18.a "tests" "POINTS"
call scripts\gen-answer.bat tests\19 tests\19.a "tests" "POINTS"
call scripts\gen-answer.bat tests\20 tests\20.a "tests" "POINTS"
call scripts\gen-answer.bat tests\21 tests\21.a "tests" "POINTS"
call scripts\gen-answer.bat tests\22 tests\22.a "tests" "POINTS"
call scripts\gen-answer.bat tests\23 tests\23.a "tests" "POINTS"
call scripts\gen-answer.bat tests\24 tests\24.a "tests" "POINTS"
call scripts\gen-answer.bat tests\25 tests\25.a "tests" "POINTS"
call scripts\gen-answer.bat tests\26 tests\26.a "tests" "POINTS"
call scripts\gen-answer.bat tests\27 tests\27.a "tests" "POINTS"
call scripts\gen-answer.bat tests\28 tests\28.a "tests" "POINTS"
call scripts\gen-answer.bat tests\29 tests\29.a "tests" "POINTS"
call scripts\gen-answer.bat tests\30 tests\30.a "tests" "POINTS"
call scripts\gen-answer.bat tests\31 tests\31.a "tests" "POINTS"
call scripts\gen-answer.bat tests\32 tests\32.a "tests" "POINTS"
call scripts\gen-answer.bat tests\33 tests\33.a "tests" "POINTS"
call scripts\gen-answer.bat tests\34 tests\34.a "tests" "POINTS"
call scripts\gen-answer.bat tests\35 tests\35.a "tests" "POINTS"
call scripts\gen-answer.bat tests\36 tests\36.a "tests" "POINTS"
call scripts\gen-answer.bat tests\37 tests\37.a "tests" "POINTS"
call scripts\gen-answer.bat tests\38 tests\38.a "tests" "POINTS"
call scripts\gen-answer.bat tests\39 tests\39.a "tests" "POINTS"
call scripts\gen-answer.bat tests\40 tests\40.a "tests" "POINTS"
call scripts\gen-answer.bat tests\41 tests\41.a "tests" "POINTS"
call scripts\gen-answer.bat tests\42 tests\42.a "tests" "POINTS"
call scripts\gen-answer.bat tests\43 tests\43.a "tests" "POINTS"
call scripts\gen-answer.bat tests\44 tests\44.a "tests" "POINTS"
call scripts\gen-answer.bat tests\45 tests\45.a "tests" "POINTS"
call scripts\gen-answer.bat tests\46 tests\46.a "tests" "POINTS"
call scripts\gen-answer.bat tests\47 tests\47.a "tests" "POINTS"
call scripts\gen-answer.bat tests\48 tests\48.a "tests" "POINTS"
call scripts\gen-answer.bat tests\49 tests\49.a "tests" "POINTS"
call scripts\gen-answer.bat tests\50 tests\50.a "tests" "POINTS"
call scripts\gen-answer.bat tests\51 tests\51.a "tests" "POINTS"

262
exam-queue-17/doall.sh Normal file
View File

@@ -0,0 +1,262 @@
#!/usr/bin/env bash
# *** validation ***
scripts/run-validator-tests.sh
scripts/run-checker-tests.sh
# *** tests ***
mkdir -p tests
echo "Generating test #2"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 1 5 10 5 10 1 100" "tests/02" 2
echo "Generating test #3"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 2 5 10 5 10 1 100" "tests/03" 3
echo "Generating test #4"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 3 5 10 5 10 1 100" "tests/04" 4
echo "Generating test #5"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 4 5 10 5 10 1 100" "tests/05" 5
echo "Generating test #6"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 5 5 10 5 10 1 100" "tests/06" 6
echo "Generating test #7"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 1 50 100 500 1000 1 1000000" "tests/07" 7
echo "Generating test #8"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 2 50 100 500 1000 1 1000000" "tests/08" 8
echo "Generating test #9"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 3 50 100 500 1000 1 1000000" "tests/09" 9
echo "Generating test #10"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 4 50 100 500 1000 1 1000000" "tests/10" 10
echo "Generating test #11"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 5 50 100 500 1000 1 1000000" "tests/11" 11
echo "Generating test #12"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 1 50000 100000 50000 100000 1 1000000000" "tests/12" 12
echo "Generating test #13"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 2 50000 100000 50000 100000 1 1000000000" "tests/13" 13
echo "Generating test #14"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 3 50000 100000 50000 100000 1 1000000000" "tests/14" 14
echo "Generating test #15"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 4 50000 100000 50000 100000 1 1000000000" "tests/15" 15
echo "Generating test #16"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 5 50000 100000 50000 100000 1 1000000000" "tests/16" 16
echo "Generating test #17"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 6 50000 100000 50000 100000 1 1000000000" "tests/17" 17
echo "Generating test #18"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 7 50000 100000 50000 100000 1 1000000000" "tests/18" 18
echo "Generating test #19"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 8 50000 100000 50000 100000 1 1000000000" "tests/19" 19
echo "Generating test #20"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 9 50000 100000 50000 100000 1 1000000000" "tests/20" 20
echo "Generating test #21"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 10 50000 100000 50000 100000 1 1000000000" "tests/21" 21
echo "Generating test #22"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 1 100000 100000 100000 100000 1 1000000000" "tests/22" 22
echo "Generating test #23"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 2 100000 100000 100000 100000 1 1000000000" "tests/23" 23
echo "Generating test #24"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 3 100000 100000 100000 100000 1 1000000000" "tests/24" 24
echo "Generating test #25"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 4 100000 100000 100000 100000 1 1000000000" "tests/25" 25
echo "Generating test #26"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 5 100000 100000 100000 100000 1 1000000000" "tests/26" 26
echo "Generating test #27"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 6 100000 100000 100000 100000 1 1000000000" "tests/27" 27
echo "Generating test #28"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 7 100000 100000 100000 100000 1 1000000000" "tests/28" 28
echo "Generating test #29"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 8 100000 100000 100000 100000 1 1000000000" "tests/29" 29
echo "Generating test #30"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 9 100000 100000 100000 100000 1 1000000000" "tests/30" 30
echo "Generating test #31"
scripts/gen-input-via-stdout.sh "wine files/gen.exe 10 100000 100000 100000 100000 1 1000000000" "tests/31" 31
echo "Generating test #32"
scripts/gen-input-via-stdout.sh "wine files/gen1.exe 1 100000 100000 100000 100000 1 1000000000" "tests/32" 32
echo "Generating test #33"
scripts/gen-input-via-stdout.sh "wine files/gen1.exe 2 100000 100000 100000 100000 1 1000000000" "tests/33" 33
echo "Generating test #34"
scripts/gen-input-via-stdout.sh "wine files/gen1.exe 3 100000 100000 100000 100000 1 1000000000" "tests/34" 34
echo "Generating test #35"
scripts/gen-input-via-stdout.sh "wine files/gen1.exe 4 100000 100000 100000 100000 1 1000000000" "tests/35" 35
echo "Generating test #36"
scripts/gen-input-via-stdout.sh "wine files/gen1.exe 5 100000 100000 100000 100000 1 1000000000" "tests/36" 36
echo "Generating test #37"
scripts/gen-input-via-stdout.sh "wine files/gen2.exe 1 100000 100000 100000 100000 1 1000000000" "tests/37" 37
echo "Generating test #38"
scripts/gen-input-via-stdout.sh "wine files/gen2.exe 2 100000 100000 100000 100000 1 1000000000" "tests/38" 38
echo "Generating test #39"
scripts/gen-input-via-stdout.sh "wine files/gen2.exe 3 100000 100000 100000 100000 1 1000000000" "tests/39" 39
echo "Generating test #40"
scripts/gen-input-via-stdout.sh "wine files/gen2.exe 4 100000 100000 100000 100000 1 1000000000" "tests/40" 40
echo "Generating test #41"
scripts/gen-input-via-stdout.sh "wine files/gen2.exe 5 100000 100000 100000 100000 1 1000000000" "tests/41" 41
echo "Generating test #42"
scripts/gen-input-via-stdout.sh "wine files/print.exe 1" "tests/42" 42
echo "Generating test #43"
scripts/gen-input-via-stdout.sh "wine files/print.exe 2" "tests/43" 43
echo "Generating test #44"
scripts/gen-input-via-stdout.sh "wine files/print.exe 3" "tests/44" 44
echo "Generating test #45"
scripts/gen-input-via-stdout.sh "wine files/print.exe 4" "tests/45" 45
echo "Generating test #46"
scripts/gen-input-via-stdout.sh "wine files/print.exe 5" "tests/46" 46
echo "Generating test #47"
scripts/gen-input-via-stdout.sh "wine files/print.exe 6" "tests/47" 47
echo "Generating test #48"
scripts/gen-input-via-stdout.sh "wine files/print.exe 7" "tests/48" 48
echo "Generating test #49"
scripts/gen-input-via-stdout.sh "wine files/print.exe 8" "tests/49" 49
echo "Generating test #50"
scripts/gen-input-via-stdout.sh "wine files/print.exe 9" "tests/50" 50
echo "Generating test #51"
scripts/gen-input-via-stdout.sh "wine files/print.exe 10" "tests/51" 51
echo ""
echo "Generating answer for test #1"
scripts/gen-answer.sh tests/01 tests/01.a "tests" "SAMPLES"
echo ""
echo "Generating answer for test #2"
scripts/gen-answer.sh tests/02 tests/02.a "tests" "POINTS"
echo ""
echo "Generating answer for test #3"
scripts/gen-answer.sh tests/03 tests/03.a "tests" "POINTS"
echo ""
echo "Generating answer for test #4"
scripts/gen-answer.sh tests/04 tests/04.a "tests" "POINTS"
echo ""
echo "Generating answer for test #5"
scripts/gen-answer.sh tests/05 tests/05.a "tests" "POINTS"
echo ""
echo "Generating answer for test #6"
scripts/gen-answer.sh tests/06 tests/06.a "tests" "POINTS"
echo ""
echo "Generating answer for test #7"
scripts/gen-answer.sh tests/07 tests/07.a "tests" "POINTS"
echo ""
echo "Generating answer for test #8"
scripts/gen-answer.sh tests/08 tests/08.a "tests" "POINTS"
echo ""
echo "Generating answer for test #9"
scripts/gen-answer.sh tests/09 tests/09.a "tests" "POINTS"
echo ""
echo "Generating answer for test #10"
scripts/gen-answer.sh tests/10 tests/10.a "tests" "POINTS"
echo ""
echo "Generating answer for test #11"
scripts/gen-answer.sh tests/11 tests/11.a "tests" "POINTS"
echo ""
echo "Generating answer for test #12"
scripts/gen-answer.sh tests/12 tests/12.a "tests" "POINTS"
echo ""
echo "Generating answer for test #13"
scripts/gen-answer.sh tests/13 tests/13.a "tests" "POINTS"
echo ""
echo "Generating answer for test #14"
scripts/gen-answer.sh tests/14 tests/14.a "tests" "POINTS"
echo ""
echo "Generating answer for test #15"
scripts/gen-answer.sh tests/15 tests/15.a "tests" "POINTS"
echo ""
echo "Generating answer for test #16"
scripts/gen-answer.sh tests/16 tests/16.a "tests" "POINTS"
echo ""
echo "Generating answer for test #17"
scripts/gen-answer.sh tests/17 tests/17.a "tests" "POINTS"
echo ""
echo "Generating answer for test #18"
scripts/gen-answer.sh tests/18 tests/18.a "tests" "POINTS"
echo ""
echo "Generating answer for test #19"
scripts/gen-answer.sh tests/19 tests/19.a "tests" "POINTS"
echo ""
echo "Generating answer for test #20"
scripts/gen-answer.sh tests/20 tests/20.a "tests" "POINTS"
echo ""
echo "Generating answer for test #21"
scripts/gen-answer.sh tests/21 tests/21.a "tests" "POINTS"
echo ""
echo "Generating answer for test #22"
scripts/gen-answer.sh tests/22 tests/22.a "tests" "POINTS"
echo ""
echo "Generating answer for test #23"
scripts/gen-answer.sh tests/23 tests/23.a "tests" "POINTS"
echo ""
echo "Generating answer for test #24"
scripts/gen-answer.sh tests/24 tests/24.a "tests" "POINTS"
echo ""
echo "Generating answer for test #25"
scripts/gen-answer.sh tests/25 tests/25.a "tests" "POINTS"
echo ""
echo "Generating answer for test #26"
scripts/gen-answer.sh tests/26 tests/26.a "tests" "POINTS"
echo ""
echo "Generating answer for test #27"
scripts/gen-answer.sh tests/27 tests/27.a "tests" "POINTS"
echo ""
echo "Generating answer for test #28"
scripts/gen-answer.sh tests/28 tests/28.a "tests" "POINTS"
echo ""
echo "Generating answer for test #29"
scripts/gen-answer.sh tests/29 tests/29.a "tests" "POINTS"
echo ""
echo "Generating answer for test #30"
scripts/gen-answer.sh tests/30 tests/30.a "tests" "POINTS"
echo ""
echo "Generating answer for test #31"
scripts/gen-answer.sh tests/31 tests/31.a "tests" "POINTS"
echo ""
echo "Generating answer for test #32"
scripts/gen-answer.sh tests/32 tests/32.a "tests" "POINTS"
echo ""
echo "Generating answer for test #33"
scripts/gen-answer.sh tests/33 tests/33.a "tests" "POINTS"
echo ""
echo "Generating answer for test #34"
scripts/gen-answer.sh tests/34 tests/34.a "tests" "POINTS"
echo ""
echo "Generating answer for test #35"
scripts/gen-answer.sh tests/35 tests/35.a "tests" "POINTS"
echo ""
echo "Generating answer for test #36"
scripts/gen-answer.sh tests/36 tests/36.a "tests" "POINTS"
echo ""
echo "Generating answer for test #37"
scripts/gen-answer.sh tests/37 tests/37.a "tests" "POINTS"
echo ""
echo "Generating answer for test #38"
scripts/gen-answer.sh tests/38 tests/38.a "tests" "POINTS"
echo ""
echo "Generating answer for test #39"
scripts/gen-answer.sh tests/39 tests/39.a "tests" "POINTS"
echo ""
echo "Generating answer for test #40"
scripts/gen-answer.sh tests/40 tests/40.a "tests" "POINTS"
echo ""
echo "Generating answer for test #41"
scripts/gen-answer.sh tests/41 tests/41.a "tests" "POINTS"
echo ""
echo "Generating answer for test #42"
scripts/gen-answer.sh tests/42 tests/42.a "tests" "POINTS"
echo ""
echo "Generating answer for test #43"
scripts/gen-answer.sh tests/43 tests/43.a "tests" "POINTS"
echo ""
echo "Generating answer for test #44"
scripts/gen-answer.sh tests/44 tests/44.a "tests" "POINTS"
echo ""
echo "Generating answer for test #45"
scripts/gen-answer.sh tests/45 tests/45.a "tests" "POINTS"
echo ""
echo "Generating answer for test #46"
scripts/gen-answer.sh tests/46 tests/46.a "tests" "POINTS"
echo ""
echo "Generating answer for test #47"
scripts/gen-answer.sh tests/47 tests/47.a "tests" "POINTS"
echo ""
echo "Generating answer for test #48"
scripts/gen-answer.sh tests/48 tests/48.a "tests" "POINTS"
echo ""
echo "Generating answer for test #49"
scripts/gen-answer.sh tests/49 tests/49.a "tests" "POINTS"
echo ""
echo "Generating answer for test #50"
scripts/gen-answer.sh tests/50 tests/50.a "tests" "POINTS"
echo ""
echo "Generating answer for test #51"
scripts/gen-answer.sh tests/51 tests/51.a "tests" "POINTS"
echo ""

View File

@@ -0,0 +1,57 @@
#include "testlib.h"
#include <sstream>
using namespace std;
int main(int argc, char * argv[])
{
setName("compare ordered sequences of signed int%d numbers", 8 * int(sizeof(long long)));
registerTestlibCmd(argc, argv);
int n = 0;
string firstElems;
while (!ans.seekEof() && !ouf.seekEof())
{
n++;
long long j = ans.readLong();
long long p = ouf.readLong();
if (j != p)
quitf(_wa, "%d%s numbers differ - expected: '%s', found: '%s'", n, englishEnding(n).c_str(), vtos(j).c_str(), vtos(p).c_str());
else
if (n <= 5)
{
if (firstElems.length() > 0)
firstElems += " ";
firstElems += vtos(j);
}
}
int extraInAnsCount = 0;
while (!ans.seekEof())
{
ans.readLong();
extraInAnsCount++;
}
int extraInOufCount = 0;
while (!ouf.seekEof())
{
ouf.readLong();
extraInOufCount++;
}
if (extraInAnsCount > 0)
quitf(_wa, "Answer contains longer sequence [length = %d], but output contains %d elements", n + extraInAnsCount, n);
if (extraInOufCount > 0)
quitf(_wa, "Output contains longer sequence [length = %d], but answer contains %d elements", n + extraInOufCount, n);
if (n <= 5)
quitf(_ok, "%d number(s): \"%s\"", n, compress(firstElems).c_str());
else
quitf(_ok, "%d numbers", n);
}

281
exam-queue-17/files/gen.cpp Normal file
View File

@@ -0,0 +1,281 @@
#include<bits/stdc++.h>
#ifndef KRAKOZYABRA
#include "testlib.h"
#else
#include "testliblochal.h"
#endif // KRAKOZYABRA
using namespace std;
template <typename T>
class ordered_set {
private:
struct Node {
T data;
int weight; // Number of nodes in the subtree rooted at this node
std::unique_ptr<Node> left;
std::unique_ptr<Node> right;
Node(const T& data) : data(data), weight(1), left(nullptr), right(nullptr) {}
};
std::unique_ptr<Node> root;
// Helper function to update the weight of a node
void update_weight(Node* node) {
if (node) {
node->weight = 1;
if (node->left) node->weight += node->left->weight;
if (node->right) node->weight += node->right->weight;
}
}
// Helper function for insertion
Node* insert_recursive(Node* node, const T& data) {
if (!node) {
return new Node(data);
}
if (data < node->data) {
node->left.reset(insert_recursive(node->left.release(), data)); //Release ownership before recursive call
}
else {
node->right.reset(insert_recursive(node->right.release(), data)); //Release ownership before recursive call
}
update_weight(node);
return node;
}
// Helper function for deletion (find minimum in right subtree)
Node* find_min(Node* node) {
while (node->left) {
node = node->left.get(); // Access the raw pointer
}
return node;
}
// Helper function for deletion
Node* delete_recursive(Node* node, const T& data) {
if (!node) {
return nullptr; // Value not found
}
if (data < node->data) {
node->left.reset(delete_recursive(node->left.release(), data)); //Release ownership before recursive call
}
else if (data > node->data) {
node->right.reset(delete_recursive(node->right.release(), data)); //Release ownership before recursive call
}
else {
// Node to be deleted found
// Case 1: Node with no child or only one child
if (!node->left) {
Node* temp = node->right.release();
delete node;
return temp;
}
else if (!node->right) {
Node* temp = node->left.release();
delete node;
return temp;
}
// Case 2: Node with two children
Node* temp = find_min(node->right.get());
node->data = temp->data;
node->right.reset(delete_recursive(node->right.release(), temp->data));
}
update_weight(node);
return node;
}
//Helper for get_element_at_index (find the k-th smallest element).
T get_element_at_index_recursive(Node* node, int index) {
if (!node) {
throw std::out_of_range("Index out of range");
}
int left_subtree_size = (node->left) ? node->left->weight : 0;
if (index == left_subtree_size) {
return node->data;
}
else if (index < left_subtree_size) {
return get_element_at_index_recursive(node->left.get(), index);
}
else {
return get_element_at_index_recursive(node->right.get(), index - left_subtree_size - 1);
}
}
//Helper to perform inorder traversal
void inorder_traversal_recursive(Node* node, std::vector<T>& result) const {
if (node) {
inorder_traversal_recursive(node->left.get(), result);
result.push_back(node->data);
inorder_traversal_recursive(node->right.get(), result);
}
}
//Helper to find index of an element.
int get_index_of_element_recursive(Node* node, const T& target, int current_rank) const {
if (!node) {
return -1; // Element not found
}
int left_subtree_size = (node->left) ? node->left->weight : 0;
if (target == node->data) {
return current_rank + left_subtree_size;
}
else if (target < node->data) {
return get_index_of_element_recursive(node->left.get(), target, current_rank);
}
else {
return get_index_of_element_recursive(node->right.get(), target, current_rank + left_subtree_size + 1);
}
}
public:
ordered_set() : root(nullptr) {}
void insert(const T& data) {
if (!root) {
root = std::make_unique<Node>(data);
}
else {
root.reset(insert_recursive(root.release(), data)); //Release ownership before recursive call
}
}
void erase(const T& data) {
root.reset(delete_recursive(root.release(), data)); //Release ownership before recursive call
}
T get_element(int index) {
if (index < 0 || index >= size()) {
throw std::out_of_range("Index out of range");
}
return get_element_at_index_recursive(root.get(), index);
}
int size() const {
return (root) ? root->weight : 0;
}
bool empty() const {
return root == nullptr;
}
void clear() {
root.reset(); // Effectively deletes the entire tree
}
// Returns a vector of the elements in sorted order (inorder traversal)
std::vector<T> inorder_traversal() const {
std::vector<T> result;
inorder_traversal_recursive(root.get(), result);
return result;
}
// Added function to get the index of an element
int get_index(const T target) const {
return get_index_of_element_recursive(root.get(), target, 0);
}
};
int main(int argc, char* argv[]) {
#ifndef KRAKOZYABRA
registerGen(argc, argv, 1);
#endif // KRAKOZYABRA
int minN = opt<int>(2), maxN = opt<int>(3);
int minM = opt<int>(4), maxM = opt<int>(5);
int minA = opt<int>(6), maxA = opt<int>(7);
int n = rnd.next(minN, maxN);
int m = rnd.next(minM, maxM);
cout << n << ' ' << m << '\n';
ordered_set<int> st;
vector<int> a;
while (a.size() < n) {
int aa = rnd.next(minA, maxA);
if (st.get_index(aa) == -1) {
a.push_back(aa);
st.insert(aa);
}
}
auto getrndin = [&]() {
if (st.size() == 0)
return -1;
int sz = st.size();
int i = rnd.next(0, sz - 1);
return st.get_element(i);
};
auto getrndnew = [&]() {
int aa = rnd.next(minA, maxA);
while (st.get_index(aa) != -1)
aa = rnd.next(minA, maxA);
return aa;
};
for (int i = 0; i < n; i++)
cout << a[i] << " \n"[i == n - 1];
for (int i = 0; i < m; i++) {
int t = 0;
if (st.size() == 0)
t = 2;
else
t = rnd.next(1, 3);
if (t == 1) {
int x = getrndnew();
int y = getrndin();
st.insert(x);
cout << t << ' ' << x << ' ' << y << '\n';
}
if (t == 2) {
int x = getrndnew();
st.insert(x);
cout << t << ' ' << x << '\n';
}
if (t == 3) {
int x = getrndin();
st.erase(x);
cout << t << ' ' << x << '\n';
}
}
}
//#pragma once
//#include <bits/stdc++.h>
//#include <random>
//#include <optional>
//
//using namespace std;
//
//random_device rd;
//mt19937 gen(rd());
//
//template <typename T>
//T opt(T value) {
// FILE* stream;
// freopen_s(&stream, "params.txt", "r", stdin);
// T res;
// for (int i = 0; i < value; i++)
// cin >> res;
// return res;
//}
//
//class Random {
//public:
// long long next(long long a, long long b) {
// return a + gen() % (b - a + 1);
// };
//};
//
//Random rnd;

BIN
exam-queue-17/files/gen.exe Normal file

Binary file not shown.

View File

@@ -0,0 +1,280 @@
#include<bits/stdc++.h>
#ifndef KRAKOZYABRA
#include "testlib.h"
#else
#include "testliblochal.h"
#endif // KRAKOZYABRA
using namespace std;
template <typename T>
class ordered_set {
private:
struct Node {
T data;
int weight; // Number of nodes in the subtree rooted at this node
std::unique_ptr<Node> left;
std::unique_ptr<Node> right;
Node(const T& data) : data(data), weight(1), left(nullptr), right(nullptr) {}
};
std::unique_ptr<Node> root;
// Helper function to update the weight of a node
void update_weight(Node* node) {
if (node) {
node->weight = 1;
if (node->left) node->weight += node->left->weight;
if (node->right) node->weight += node->right->weight;
}
}
// Helper function for insertion
Node* insert_recursive(Node* node, const T& data) {
if (!node) {
return new Node(data);
}
if (data < node->data) {
node->left.reset(insert_recursive(node->left.release(), data)); //Release ownership before recursive call
}
else {
node->right.reset(insert_recursive(node->right.release(), data)); //Release ownership before recursive call
}
update_weight(node);
return node;
}
// Helper function for deletion (find minimum in right subtree)
Node* find_min(Node* node) {
while (node->left) {
node = node->left.get(); // Access the raw pointer
}
return node;
}
// Helper function for deletion
Node* delete_recursive(Node* node, const T& data) {
if (!node) {
return nullptr; // Value not found
}
if (data < node->data) {
node->left.reset(delete_recursive(node->left.release(), data)); //Release ownership before recursive call
}
else if (data > node->data) {
node->right.reset(delete_recursive(node->right.release(), data)); //Release ownership before recursive call
}
else {
// Node to be deleted found
// Case 1: Node with no child or only one child
if (!node->left) {
Node* temp = node->right.release();
delete node;
return temp;
}
else if (!node->right) {
Node* temp = node->left.release();
delete node;
return temp;
}
// Case 2: Node with two children
Node* temp = find_min(node->right.get());
node->data = temp->data;
node->right.reset(delete_recursive(node->right.release(), temp->data));
}
update_weight(node);
return node;
}
//Helper for get_element_at_index (find the k-th smallest element).
T get_element_at_index_recursive(Node* node, int index) {
if (!node) {
throw std::out_of_range("Index out of range");
}
int left_subtree_size = (node->left) ? node->left->weight : 0;
if (index == left_subtree_size) {
return node->data;
}
else if (index < left_subtree_size) {
return get_element_at_index_recursive(node->left.get(), index);
}
else {
return get_element_at_index_recursive(node->right.get(), index - left_subtree_size - 1);
}
}
//Helper to perform inorder traversal
void inorder_traversal_recursive(Node* node, std::vector<T>& result) const {
if (node) {
inorder_traversal_recursive(node->left.get(), result);
result.push_back(node->data);
inorder_traversal_recursive(node->right.get(), result);
}
}
//Helper to find index of an element.
int get_index_of_element_recursive(Node* node, const T& target, int current_rank) const {
if (!node) {
return -1; // Element not found
}
int left_subtree_size = (node->left) ? node->left->weight : 0;
if (target == node->data) {
return current_rank + left_subtree_size;
}
else if (target < node->data) {
return get_index_of_element_recursive(node->left.get(), target, current_rank);
}
else {
return get_index_of_element_recursive(node->right.get(), target, current_rank + left_subtree_size + 1);
}
}
public:
ordered_set() : root(nullptr) {}
void insert(const T& data) {
if (!root) {
root = std::make_unique<Node>(data);
}
else {
root.reset(insert_recursive(root.release(), data)); //Release ownership before recursive call
}
}
void erase(const T& data) {
root.reset(delete_recursive(root.release(), data)); //Release ownership before recursive call
}
T get_element(int index) {
if (index < 0 || index >= size()) {
throw std::out_of_range("Index out of range");
}
return get_element_at_index_recursive(root.get(), index);
}
int size() const {
return (root) ? root->weight : 0;
}
bool empty() const {
return root == nullptr;
}
void clear() {
root.reset(); // Effectively deletes the entire tree
}
// Returns a vector of the elements in sorted order (inorder traversal)
std::vector<T> inorder_traversal() const {
std::vector<T> result;
inorder_traversal_recursive(root.get(), result);
return result;
}
// Added function to get the index of an element
int get_index(const T target) const {
return get_index_of_element_recursive(root.get(), target, 0);
}
};
int main(int argc, char* argv[]) {
#ifndef KRAKOZYABRA
registerGen(argc, argv, 1);
#endif // KRAKOZYABRA
int minN = opt<int>(2), maxN = opt<int>(3);
int minM = opt<int>(4), maxM = opt<int>(5);
int minA = opt<int>(6), maxA = opt<int>(7);
int n = rnd.next(minN, maxN);
int m = rnd.next(minM, maxM);
cout << n << ' ' << m << '\n';
ordered_set<int> st;
vector<int> a;
while (a.size() < n) {
int aa = rnd.next(minA, maxA);
if (st.get_index(aa) == -1) {
a.push_back(aa);
st.insert(aa);
}
}
auto getrndin = [&]() {
if (st.size() == 0)
return -1;
int sz = st.size();
int i = rnd.next(0, sz - 1);
return st.get_element(i);
};
auto getrndnew = [&]() {
int aa = rnd.next(minA, maxA);
while (st.get_index(aa) != -1)
aa = rnd.next(minA, maxA);
return aa;
};
for (int i = 0; i < n; i++)
cout << a[i] << " \n"[i == n - 1];
for (int i = 0; i < m; i++) {
int t = 1;
//if (st.size() == 0)
// t = 2;
//else
// t = rnd.next(1, 3);
if (t == 1) {
int x = getrndnew();
int y = getrndin();
st.insert(x);
cout << t << ' ' << x << ' ' << y << '\n';
}
if (t == 2) {
int x = getrndnew();
st.insert(x);
cout << t << ' ' << x << '\n';
}
if (t == 3) {
int x = getrndin();
st.erase(x);
cout << t << ' ' << x << '\n';
}
}
}
//#pragma once
//#include <bits/stdc++.h>
//#include <random>
//
//using namespace std;
//
//random_device rd;
//mt19937 gen(rd());
//
//template <typename T>
//T opt(T value) {
// FILE* stream;
// freopen_s(&stream, "params.txt", "r", stdin);
// T res;
// for (int i = 0; i < value; i++)
// cin >> res;
// return res;
//}
//
//class Random {
//public:
// long long next(long long a, long long b) {
// return a + gen() % (b - a + 1);
// };
//};
//
//Random rnd;

Binary file not shown.

View File

@@ -0,0 +1,276 @@
#include<bits/stdc++.h>
#ifndef KRAKOZYABRA
#include "testlib.h"
#else
#include "testliblochal.h"
#endif // KRAKOZYABRA
using namespace std;
template <typename T>
class ordered_set {
private:
struct Node {
T data;
int weight; // Number of nodes in the subtree rooted at this node
std::unique_ptr<Node> left;
std::unique_ptr<Node> right;
Node(const T& data) : data(data), weight(1), left(nullptr), right(nullptr) {}
};
std::unique_ptr<Node> root;
// Helper function to update the weight of a node
void update_weight(Node* node) {
if (node) {
node->weight = 1;
if (node->left) node->weight += node->left->weight;
if (node->right) node->weight += node->right->weight;
}
}
// Helper function for insertion
Node* insert_recursive(Node* node, const T& data) {
if (!node) {
return new Node(data);
}
if (data < node->data) {
node->left.reset(insert_recursive(node->left.release(), data)); //Release ownership before recursive call
}
else {
node->right.reset(insert_recursive(node->right.release(), data)); //Release ownership before recursive call
}
update_weight(node);
return node;
}
// Helper function for deletion (find minimum in right subtree)
Node* find_min(Node* node) {
while (node->left) {
node = node->left.get(); // Access the raw pointer
}
return node;
}
// Helper function for deletion
Node* delete_recursive(Node* node, const T& data) {
if (!node) {
return nullptr; // Value not found
}
if (data < node->data) {
node->left.reset(delete_recursive(node->left.release(), data)); //Release ownership before recursive call
}
else if (data > node->data) {
node->right.reset(delete_recursive(node->right.release(), data)); //Release ownership before recursive call
}
else {
// Node to be deleted found
// Case 1: Node with no child or only one child
if (!node->left) {
Node* temp = node->right.release();
delete node;
return temp;
}
else if (!node->right) {
Node* temp = node->left.release();
delete node;
return temp;
}
// Case 2: Node with two children
Node* temp = find_min(node->right.get());
node->data = temp->data;
node->right.reset(delete_recursive(node->right.release(), temp->data));
}
update_weight(node);
return node;
}
//Helper for get_element_at_index (find the k-th smallest element).
T get_element_at_index_recursive(Node* node, int index) {
if (!node) {
throw std::out_of_range("Index out of range");
}
int left_subtree_size = (node->left) ? node->left->weight : 0;
if (index == left_subtree_size) {
return node->data;
}
else if (index < left_subtree_size) {
return get_element_at_index_recursive(node->left.get(), index);
}
else {
return get_element_at_index_recursive(node->right.get(), index - left_subtree_size - 1);
}
}
//Helper to perform inorder traversal
void inorder_traversal_recursive(Node* node, std::vector<T>& result) const {
if (node) {
inorder_traversal_recursive(node->left.get(), result);
result.push_back(node->data);
inorder_traversal_recursive(node->right.get(), result);
}
}
//Helper to find index of an element.
int get_index_of_element_recursive(Node* node, const T& target, int current_rank) const {
if (!node) {
return -1; // Element not found
}
int left_subtree_size = (node->left) ? node->left->weight : 0;
if (target == node->data) {
return current_rank + left_subtree_size;
}
else if (target < node->data) {
return get_index_of_element_recursive(node->left.get(), target, current_rank);
}
else {
return get_index_of_element_recursive(node->right.get(), target, current_rank + left_subtree_size + 1);
}
}
public:
ordered_set() : root(nullptr) {}
void insert(const T& data) {
if (!root) {
root = std::make_unique<Node>(data);
}
else {
root.reset(insert_recursive(root.release(), data)); //Release ownership before recursive call
}
}
void erase(const T& data) {
root.reset(delete_recursive(root.release(), data)); //Release ownership before recursive call
}
T get_element(int index) {
if (index < 0 || index >= size()) {
throw std::out_of_range("Index out of range");
}
return get_element_at_index_recursive(root.get(), index);
}
int size() const {
return (root) ? root->weight : 0;
}
bool empty() const {
return root == nullptr;
}
void clear() {
root.reset(); // Effectively deletes the entire tree
}
// Returns a vector of the elements in sorted order (inorder traversal)
std::vector<T> inorder_traversal() const {
std::vector<T> result;
inorder_traversal_recursive(root.get(), result);
return result;
}
// Added function to get the index of an element
int get_index(const T target) const {
return get_index_of_element_recursive(root.get(), target, 0);
}
};
int main(int argc, char* argv[]) {
#ifndef KRAKOZYABRA
registerGen(argc, argv, 1);
#endif // KRAKOZYABRA
int minN = opt<int>(2), maxN = opt<int>(3);
int minM = opt<int>(4), maxM = opt<int>(5);
int minA = opt<int>(6), maxA = opt<int>(7);
int n = rnd.next(minN, maxN);
int m = rnd.next(minM, maxM);
cout << n << ' ' << m << '\n';
ordered_set<int> st;
vector<int> a;
while (a.size() < n) {
int aa = rnd.next(minA, maxA);
if (st.get_index(aa) == -1) {
a.push_back(aa);
st.insert(aa);
}
}
auto getrndin = [&]() {
if (st.size() == 0)
return -1;
int sz = st.size();
int i = rnd.next(0, sz - 1);
return st.get_element(i);
};
auto getrndnew = [&]() {
int aa = rnd.next(minA, maxA);
while (st.get_index(aa) != -1)
aa = rnd.next(minA, maxA);
return aa;
};
for (int i = 0; i < n; i++)
cout << a[i] << " \n"[i == n - 1];
for (int i = 0; i < m; i++) {
int t = rnd.next(1, 2);
if (t == 1) {
int x = getrndnew();
int y = getrndin();
st.insert(x);
cout << t << ' ' << x << ' ' << y << '\n';
}
if (t == 2) {
int x = getrndnew();
st.insert(x);
cout << t << ' ' << x << '\n';
}
if (t == 3) {
int x = getrndin();
st.erase(x);
cout << t << ' ' << x << '\n';
}
}
}
//#pragma once
//#include <bits/stdc++.h>
//#include <random>
//
//using namespace std;
//
//random_device rd;
//mt19937 gen(rd());
//
//template <typename T>
//T opt(T value) {
// FILE* stream;
// freopen_s(&stream, "params.txt", "r", stdin);
// T res;
// for (int i = 0; i < value; i++)
// cin >> res;
// return res;
//}
//
//class Random {
//public:
// long long next(long long a, long long b) {
// return a + gen() % (b - a + 1);
// };
//};
//
//Random rnd;

Binary file not shown.

View File

@@ -0,0 +1,788 @@
%
% Macros for the contest problems
% for MikTeX: use latex.exe
% License: https://github.com/GassaFM/olymp.sty/blob/master/LICENSE
% Authors: https://github.com/GassaFM/olymp.sty/blob/master/AUTHORS
%
\ProvidesPackage{olymp}
\usepackage{verbatim}
\newif\if@landscape\@landscapefalse
\newif\if@russian\@russianfalse
\newif\if@ukrainian\@ukrainianfalse
\newif\if@arabic\@arabicfalse
\DeclareOption{landscape}{
\@landscapetrue
}
\DeclareOption{russian}{
\@russiantrue
}
\DeclareOption{ukrainian}{
\@ukrainiantrue
}
\DeclareOption{arabic}{
\@arabictrue
}
\ProcessOptions\relax
% -- Setup margins --
%
% Tex defines to large margins for our purposes.
% So we redefine this to use paper more efficiently
%
\newlength{\thelinewidth}
\if@landscape
\if@twocolumn
\else
\error Landscape is only supported for two column mode
\fi
\ifcase\@ptsize % 10 pt
\hoffset=-15mm
\voffset=-35mm
\textheight=165mm
\textwidth=272mm
\or % 11 pt
\hoffset=-13mm
\voffset=-36mm
\textheight=166mm
\textwidth=272mm
\or % 12 pt
\hoffset=-12mm
\voffset=-35mm
\textheight=162mm
\textwidth=268mm
\fi
\else
\ifcase\@ptsize % 10 pt
\hoffset=-26.5mm
\voffset=-35mm
\textheight=250mm
\textwidth=175mm
\or % 11 pt
\hoffset=-25mm
\voffset=-37.5mm
\textheight=255mm
\textwidth=175mm
\or % 12 pt
\hoffset=-20mm
\voffset=-35mm
\textheight=245mm
\textwidth=175mm
\fi
\if@twocolumn
\hoffset=-14.3mm
\voffset=-38mm
\textheight=255mm
\textwidth=188mm
\fi
\fi
\if@twocolumn
\thelinewidth=0.47\textwidth
\else
\thelinewidth=\textwidth
\fi
% -- End of setup margins --
%---------- From package "lastpage" ------------------
\def\lastpage@putlabel{\addtocounter{page}{-1}%
\immediate\write\@auxout{\string\newlabel{LastPage}{{}{\thepage}}}%
\addtocounter{page}{1}}
\AtEndDocument{\clearpage\lastpage@putlabel}%
%---------- end of "lastpage" ------------------
% -- Setup sizes --
\newlength{\exmpwidinf}
\newlength{\exmpwidouf}
\newlength{\exmpwidewid}
\newlength{\exmpthreewidinf}
\newlength{\exmpthreewidouf}
\newlength{\exmpthreewidnote}
\newif\ifintentionallyblankpages
\exmpwidinf=0.43\thelinewidth
\exmpwidouf=0.43\thelinewidth
\exmpwidewid=0.9\thelinewidth
\exmpthreewidinf=0.28\thelinewidth
\exmpthreewidouf=0.28\thelinewidth
\exmpthreewidnote=0.30\thelinewidth
\newlength{\afterproblemhead}
\newlength{\afterconstraints}
\renewcommand{\t}[1]{\ifmmode{\mathtt{#1}}\else{\texttt{#1}}\fi}
\if@russian
\renewcommand{\le}{\leqslant}
\renewcommand{\ge}{\geqslant}
\renewcommand{\leq}{\leqslant}
\renewcommand{\geq}{\geqslant}
\else
\if@ukrainian
\renewcommand{\le}{\leqslant}
\renewcommand{\ge}{\geqslant}
\renewcommand{\leq}{\leqslant}
\renewcommand{\geq}{\geqslant}
\else
\parindent=0mm
\parskip=1ex
\fi
\fi
% -- End of setup sizes --
% -- Setup keywords --
\if@russian
\def\kw@ProblemTutorial{Разбор задачи}
\def\kw@Problem{Задача}
\def\kw@ProblemAuthor{Автор:}
\def\kw@ProblemDeveloper{Разработчик:}
\def\kw@ProblemOrigin{Источник:}
\def\kw@InputFileName{Имя входного файла:}
\def\kw@OutputFileName{Имя выходного файла:}
\def\kw@TimeLimit{Ограничение по времени:}
\def\kw@MemoryLimit{Ограничение по памяти:}
\def\kw@Feedback{Отображение результатов:}
\def\kw@stdin{стандартный поток ввода}
\def\kw@stdout{стандартный поток вывода}
\def\kw@Specification{Спецификация}
\def\kw@Interaction{Протокол взаимодействия}
\def\kw@Input{Формат входных данных}
\def\kw@Output{Формат выходных данных}
\def\kw@Example{Пример}
\def\kw@Examples{Примеры}
\def\kwExampleNotes{Пояснение}
\def\kw@Explanation{Пояснение к примеру}
\def\kw@Explanations{Пояснения к примерам}
\def\kw@Illustration{Иллюстрация}
\def\kw@Scoring{Система оценки}
\def\kw@Note{Замечание}
\def\kw@Notes{Замечания}
\def\kw@Constraints{Ограничения}
\def\kw@version{версия}
\def\kw@revision{ревизия}
\def\kw@SubtaskOne{Подзадача 1}
\def\kw@SubtaskTwo{Подзадача 2}
\def\kw@SubtaskThree{Подзадача 3}
\def\kw@SubtaskFour{Подзадача 4}
\def\kw@SubtaskFive{Подзадача 5}
\def\kw@SubtaskSix{Подзадача 6}
\def\kw@Subtask{Подзадача}
\def\kw@points{баллы}
\def\kw@Page{Страница}
\def\kw@of{из}
\def\kw@notstated{не указан}
\def\kw@IntentionallyBlankPage{Эта страница специально оставлена пустой}
\def\kw@defaultinputname{тест}
\def\kw@defaultoutputname{ответ}
\else
\if@ukrainian
\def\kw@ProblemTutorial{Розбір задачі}
\def\kw@Problem{Задача}
\def\kw@ProblemAuthor{Автор:}
\def\kw@ProblemDeveloper{Розробник:}
\def\kw@ProblemOrigin{Джерело:}
\def\kw@InputFileName{Назва вхідного файлу:}
\def\kw@OutputFileName{Назва вихідного файлу:}
\def\kw@TimeLimit{Ліміт часу:}
\def\kw@MemoryLimit{Ліміт використання пам'яті:}
\def\kw@Feedback{Відображення результатів:}
\def\kw@stdin{стандартний потік вводу}
\def\kw@stdout{стандартний потік виводу}
\def\kw@Specification{Специфікація}
\def\kw@Interaction{Протокол взаємодії}
\def\kw@Input{Формат вхідних даних}
\def\kw@Output{Формат вихідних даних}
\def\kw@Example{Приклад}
\def\kw@Examples{Приклади}
\def\kwExampleNotes{Пояснення}
\def\kw@Explanation{Пояснення до прикладу}
\def\kw@Explanations{Пояснения до прикладів}
\def\kw@Illustration{Ілюстрація}
\def\kw@Scoring{Система оцінювання}
\def\kw@Note{Зауваження}
\def\kw@Notes{Зауваження}
\def\kw@Constraints{Обмеження}
\def\kw@version{версія}
\def\kw@revision{ревізія}
\def\kw@SubtaskOne{Підзадача 1}
\def\kw@SubtaskTwo{Підзадача 2}
\def\kw@SubtaskThree{Підзадача 3}
\def\kw@SubtaskFour{Підзадача 4}
\def\kw@SubtaskFive{Підзадача 5}
\def\kw@SubtaskSix{Підзадача 6}
\def\kw@Subtask{Підзадача}
\def\kw@points{бали}
\def\kw@Page{Сторінка}
\def\kw@of{з}
\def\kw@notstated{не вказано}
\def\kw@IntentionallyBlankPage{Ця сторінка спеціально залишена порожньою}
\def\kw@defaultinputname{тест}
\def\kw@defaultoutputname{відповідь}
\else
\def\kw@ProblemTutorial{Problem Tutorial}
\def\kw@Problem{Problem}
\def\kw@ProblemAuthor{Author:}
\def\kw@ProblemDeveloper{Developer:}
\def\kw@ProblemOrigin{Origin:}
\def\kw@InputFileName{Input file:}
\def\kw@OutputFileName{Output file:}
\def\kw@TimeLimit{Time limit:}
\def\kw@MemoryLimit{Memory limit:}
\def\kw@Feedback{Feedback:}
\def\kw@stdin{standard input}
\def\kw@stdout{standard output}
\def\kw@Specification{Specification}
\def\kw@Interaction{Interaction Protocol}
\def\kw@Input{Input}
\def\kw@Output{Output}
\def\kw@Example{Example}
\def\kw@Examples{Examples}
\def\kwExampleNotes{Notes}
\def\kw@Explanation{Explanation}
\def\kw@Explanations{Explanations}
\def\kw@Illustration{Illustration}
\def\kw@Scoring{Scoring}
\def\kw@Note{Note}
\def\kw@Notes{Notes}
\def\kw@Constraints{Constraints}
\def\kw@version{version}
\def\kw@revision{revision}
\def\kw@SubtaskOne{Subtask 1}
\def\kw@SubtaskTwo{Subtask 2}
\def\kw@SubtaskThree{Subtask 3}
\def\kw@SubtaskFour{Subtask 4}
\def\kw@SubtaskFive{Subtask 5}
\def\kw@SubtaskSix{Subtask 6}
\def\kw@Subtask{Subtask}
\def\kw@points{points}
\def\kw@Page{Page}
\def\kw@of{of}
\def\kw@notstated{not stated}
\def\kw@IntentionallyBlankPage{This page is intentionally left blank}
\def\kw@defaultinputname{test}
\def\kw@defaultoutputname{answer}
\fi
\fi
\afterproblemhead=3mm
\afterconstraints=2mm
\newcommand{\problemheadfont}{\LARGE}
\newcommand{\problemsectionfont}{\Large}
\newcommand{\problemend}{
\clearpage
\ifintentionallyblankpages
\ifodd\value{page}
\else
\vspace*{\fill}
\begin{center}
\problemheadfont\kw@IntentionallyBlankPage
\end{center}
\vspace*{\fill}
\clearpage
\fi
\fi
}
\newcommand{\problemtextfont}{\normalsize}
\newcommand{\beforeproblemsectioncaption}{\smallbreak\smallskip}
\newcommand{\afterproblemsectioncaption}{\smallskip}
\if@twocolumn
\afterproblemhead=1mm
\afterconstraints=1mm
\renewcommand{\problemheadfont}{\large}
\renewcommand{\problemsectionfont}{\normalsize}
\renewcommand{\problemend}{\par\medskip}
\renewcommand{\problemtextfont}{\footnotesize}
\renewcommand{\beforeproblemsectioncaption}{\smallbreak\smallskip}
\renewcommand{\afterproblemsectioncaption}{}
\fi
% -- End of setup keywords --
% -- Problem sections --
\newcommand{\createsection}{\@newsection}
\def\@newsection#1#2{\DeclareRobustCommand{#1}{
{\beforeproblemsectioncaption\noindent\bf\problemsectionfont
\textsf{#2}}
\nopagebreak\par\afterproblemsectioncaption}
}
\newcommand{\createsectionexample}{\@newsectionexample}
\def\@newsectionexample#1#2{\DeclareRobustCommand{#1}{
\ifdefined\NoExamples\else%
{\beforeproblemsectioncaption\noindent\bf\problemsectionfont
\textsf{#2}}
\nopagebreak\par\afterproblemsectioncaption%
\fi%
}
}
\newcommand{\createsectionpar}{\@newsectionpar}
\def\@newsectionpar#1#2{\DeclareRobustCommand{#1}[1]{
{\beforeproblemsectioncaption\noindent\bf\problemsectionfont
\textsf{#2~##1}}
\nopagebreak\par\afterproblemsectioncaption}
}
\newcommand{\createsectionpartwo}{\@newsectionpartwo}
\def\@newsectionpartwo#1#2#3{\DeclareRobustCommand{#1}[2]{
{\beforeproblemsectioncaption\noindent\problemsectionfont
\textsf{\textbf{#2}~\textbf{##1}~(##2~#3)}}
\nopagebreak\par\afterproblemsectioncaption}
}
\createsection{\Specification}{\kw@Specification}
\createsection{\Interaction}{\kw@Interaction}
\createsection{\InputFile}{\kw@Input}
\createsection{\OutputFile}{\kw@Output}
\createsectionexample{\Example}{\kw@Example}
\createsectionexample{\Examples}{\kw@Examples}
\createsection{\Explanation}{\kw@Explanation}
\createsection{\Explanations}{\kw@Explanations}
\createsection{\Illustration}{\kw@Illustration}
\createsection{\Scoring}{\kw@Scoring}
\createsection{\Note}{\kw@Note}
\createsection{\Notes}{\kw@Notes}
\createsection{\Constraints}{\kw@Constraints}
\createsection{\SubtaskOne}{\kw@SubtaskOne}
\createsection{\SubtaskTwo}{\kw@SubtaskTwo}
\createsection{\SubtaskThree}{\kw@SubtaskThree}
\createsection{\SubtaskFour}{\kw@SubtaskFour}
\createsection{\SubtaskFive}{\kw@SubtaskFive}
\createsection{\SubtaskSix}{\kw@SubtaskSix}
\createsectionpar{\Subtask}{\kw@Subtask}
\createsectionpartwo{\SubtaskWithCost}{\kw@Subtask}{\kw@points}
% -- End of problem sections
% -- Default limits definition --
\if@russian
\def\defaulttimelimit{2 секунды}
\else
\if@ukrainian
\def\defaulttimelimit{2 секунди}
\else
\def\defaulttimelimit{2 seconds}
\fi
\fi
\if@russian
\def\defaultmemorylimit{256 мебибайт}
\else
\if@ukrainian
\def\defaulttimelimit{256 мебібайт}
\else
\def\defaultmemorylimit{256 mebibytes}
\fi
\fi
% -- End of default limits definition --
% -- Problem environment --
\def\defaultproblemauthor{\textit{\kw@notstated}}
\gdef\thisproblemauthor{\defaultproblemauthor}
\def\defaultproblemdeveloper{\textit{\kw@notstated}}
\gdef\thisproblemdeveloper{\defaultproblemdeveloper}
\def\defaultproblemorigin{\textit{\kw@notstated}}
\gdef\thisproblemorigin{\defaultproblemorigin}
\newif\ifdisplayauthor
\newif\ifdisplaydeveloper
\newif\ifdisplayorigin
\newif\ifrevisionsignature
\newif\ifdisplayauthorinfooter
\newif\ifdisplaydeveloperinfooter
\newcounter{problem}
\newcounter{subtasknum}[problem]
\newcommand{\SubtaskWithScore}[1]{%
{\addtocounter{subtasknum}{1}%
\beforeproblemsectioncaption\noindent\problemsectionfont%
\textsf{\textbf{\kw@Subtask~\arabic{subtasknum}}}%
\textsf{~(\kw@points:~#1)}%
\nopagebreak\par\afterproblemsectioncaption}%
}%
\newenvironment{tutorial}[1]{%
\bigskip%
\noindent%
\refstepcounter{problem}
\textbf{\problemheadfont\textsf{\ifdefined\ShortProblemTitle\ifdefined\ProblemIndex\ProblemIndex. \fi\else\kw@Problem\ \ifdefined\ProblemIndex\ProblemIndex\else\if@arabic\arabic{problem}\else\Alph{problem}\fi\fi. \fi #1}}%
\nopagebreak%
\problemtextfont%
}
\newenvironment{@problem}[6]{
\global\let\lastproblemauthor\thisproblemauthor
\global\let\lastproblemdeveloper\thisproblemdeveloper
\global\let\lastproblemorigin\thisproblemorigin
% Hotfix
%\def\@memorylimit{#5}
%% -- Default memory limit --
%% :FIXME:
%\def\@t{#5}
%
%\ifx\@t\empty
% \def\@memorylimit{\defaultmemorylimit}
%\else
%%\ifcat\par\@t
%% \def\@memorylimit{\defaultmemorylimit}
%%\else
% \def\@memorylimit{#5}
%%\fi
%\fi
%% -- End of default memory limit --
% -- No feedback case --
% :FIXME:
\def\@t{#6}
\ifx\@t\empty
\def\@feedback{}
\else
%\ifcat\par\@t
% \def\@feedback{}
%\else
\def\@feedback{\kw@Feedback & #6 \\}
\fi
%\fi
% -- End of no feedback case --
{
\ifdefined\NoProblemHead\else%
\noindent
\refstepcounter{problem}
\textbf{\problemheadfont\textsf{%
\ifdefined\ShortProblemTitle\ifdefined\ProblemIndex\ProblemIndex. \fi\else\kw@Problem\ \ifdefined\ProblemIndex\ProblemIndex\else\if@arabic\arabic{problem}\else\Alph{problem}\fi\fi. \fi%
#1%
\ifdefined\DivisionNumber%
\if\DivisionNumber2%
{\ \textit{(Division\ \DivisionNumber)}}%
\fi%
\fi%
}}%
\nopagebreak%
\par\vspace{\afterproblemhead}%
\problemtextfont\parindent=6.5mm%
\vbox{
\begin{tabular}{l@{\extracolsep{1cm}}l}
\ifdisplayauthor%
\kw@ProblemAuthor & \thisproblemauthor \\
\fi%
\ifdisplaydeveloper%
\kw@ProblemDeveloper & \thisproblemdeveloper \\
\fi%
\ifdisplayorigin%
\kw@ProblemOrigin & \thisproblemorigin \\
\fi%
\ifdefined\NoInputFileName\else%
\ifx&#2&%
\else%
\kw@InputFileName & \texttt{#2} \\
\fi\fi%
\ifdefined\NoOutputFileName\else%
\ifx&#3&%
\else%
\kw@OutputFileName & \texttt{#3} \\
\fi\fi%
\ifdefined\NoTimeLimit\else%
\ifx&#4&%
\else%
\kw@TimeLimit & #4 \\
\fi\fi%
\ifdefined\NoMemoryLimit\else%
\ifx&#5&%
\else%
\kw@MemoryLimit & #5 \\
\fi\fi%
% \kw@MemoryLimit & \@memorylimit \\
\@feedback
\end{tabular}
}
\nopagebreak
\par\vspace{\afterconstraints}
\fi%
}
\problemtextfont
\newcommand{\InputFileName}{\ifx\relax#2\relax{\kw@defaultinputname}\else{#2}\fi}
\newcommand{\OutputFileName}{\ifx\relax#3\relax{\kw@defaultoutputname}\else{#3}\fi}
}{%
\global\let\lastproblemauthor\thisproblemauthor%
\global\let\lastproblemdeveloper\thisproblemdeveloper%
\global\let\lastproblemdorigin\thisproblemorigin%
\gdef\thisproblemauthor{\defaultproblemauthor}%
\gdef\thisproblemdeveloper{\defaultproblemdeveloper}%
\gdef\thisproblemorigin{\defaultproblemorigin}%
\problemend%
}
\def\s@tm@cr@s{
\def\widthin##1{\exmpwidinf=##1\relax}
\def\widthout##1{\exmpwidouf=##1\relax}
\def\stretchin##1{\advance\exmpwidinf by ##1\relax}
\def\stretchout##1{\advance\exmpwidouf by ##1\relax}
\@ifstar{
\error Star must not be used in example environment any more
}
}
% This is magic, which delete space after verbatiminput
\addto@hook{\every@verbatim}{\topsep=0pt\relax}
% :FIXME:
\newenvironment{example}[1][]{
\s@tm@cr@s#1
\ttfamily\obeylines\obeyspaces\frenchspacing
\newcommand{\exmp}[2]{
\ifdefined\NoExamples\else%
\begin{minipage}[t]{\exmpwidinf}\rightskip=0pt plus 1fill\relax##1\medskip\end{minipage}&
\begin{minipage}[t]{\exmpwidouf}\rightskip=0pt plus 1fill\relax##2\medskip\end{minipage}\\
\hline
\fi%
}
\newcommand{\exmpfile}[2]{
\ifdefined\NoExamples\else%
\exmp{
\verbatiminput{##1}
}{
\verbatiminput{##2}
}%
\fi%
}
\ifdefined\NoExamples\else%
\begin{tabular}{|l|l|}
\hline
\multicolumn{1}{|c|}{\bf\texttt{\InputFileName}}&
\multicolumn{1}{c|}{\bf\texttt{\OutputFileName}}\\
\hline
\fi%
}{
\ifdefined\NoExamples\else%
\end{tabular}
\fi%
}
\newenvironment{examplewide}[1][]{%
\s@tm@cr@s#1
\ttfamily\obeylines\obeyspaces\frenchspacing
\newcommand{\exmp}[2]{
\ifdefined\NoExamples\else%
\begin{tabular}{|c|}
\hline
\multicolumn{1}{|c|}{\bf\texttt{\InputFileName}}\\
\hline
\begin{minipage}[t]{\exmpwidewid}\rightskip=0pt plus 1fill\relax
##1
\medskip\end{minipage}\\
\hline
\multicolumn{1}{|c|}{\bf\texttt{\OutputFileName}}\\%
\hline
\begin{minipage}[t]{\exmpwidewid}\rightskip=0pt plus 1fill\relax
##2
\medskip\end{minipage}\\%
\hline
\end{tabular}
\fi%
}
\newcommand{\exmpfile}[2]{
\ifdefined\NoExamples\else%
\exmp{
\verbatiminput{##1}
}{
\verbatiminput{##2}
}%
\fi%
}
}{
}
\newenvironment{examplethree}[1][]{
\s@tm@cr@s#1
\ttfamily\obeylines\obeyspaces\frenchspacing
\newcommand{\exmp}[3]{
\ifdefined\NoExamples\else%
\begin{minipage}[t]{\exmpthreewidinf}\rightskip=0pt plus 1fill\relax##1\medskip\end{minipage}&
\begin{minipage}[t]{\exmpthreewidouf}\rightskip=0pt plus 1fill\relax##2\medskip\end{minipage}&
\begin{minipage}[t]{\exmpthreewidnote}\rightskip=0pt plus 1fill\relax##3\medskip\end{minipage}\\
\hline
\fi%
}
\newcommand{\exmpfile}[3]{
\ifdefined\NoExamples\else%
\exmp{
\verbatiminput{##1}
}{
\verbatiminput{##2}
}{
##3
}%
\fi%
}
\ifdefined\NoExamples\else%
\begin{tabular}{|l|l|l|}
\hline
\multicolumn{1}{|c|}{\bf\texttt{\InputFileName}}&
\multicolumn{1}{|c|}{\bf\texttt{\OutputFileName}}&
\multicolumn{1}{|c|}{\bf\texttt{\expandafter\unexpanded{\expandafter\kwExampleNotes}}}\\
\hline
\fi%
}{
\ifdefined\NoExamples\else%
\end{tabular}
\fi%
}
% -- This is hack to make feedback argument optional
\newenvironment{problem}[5]{%
\def\@ProblemCommon{\begin{@problem}{#1}{#2}{#3}{#4}{#5}}%
\newcommand\@problemSix[1]{\@ProblemCommon{##1}}%
\newcommand\@problemFive{\@ProblemCommon{}}%
\@ifnextchar\bgroup\@problemSix\@problemFive%
}{%
\end{@problem}%
}
% -- End of problem environment --
% -- Declare "shortitems" and "shortnums" environment: it's a "compact itemize" --
\if@twocolumn
\def\shortitems{\vspace{-1mmplus6mm}\itemize\itemsep-0.618mmplus0.5mm\relax}%
\def\endshortitems{\vspace{-1mmplus6mm}\enditemize}%
\def\shortnums{\vspace{-1mmplus6mm}\enumerate\itemsep-0.618mmplus0.5mm\relax}%
\def\endshortnums{\vspace{-1mmplus6mm}\endenumerate}%
\else
\def\shortitems{\vspace{-3mmplus2mm}\itemize\itemsep-1.618mmplus0.5mm\relax}%
\def\endshortitems{\vspace{-3mmplus2mm}\enditemize}%
\def\shortnums{\vspace{-3mmplus2mm}\enumerate\itemsep-1.618mmplus0.5mm\relax}%
\def\endshortnums{\vspace{-3mmplus2mm}\endenumerate}%
\fi
% -- end of "shortitems" and "shortnums" declaration --
\newcommand{\thecontestname}{Olympiad in Informatics}
\newcommand{\thecontestlocation}{Somewhere}
\newcommand{\thecontestdate}{Once upon a time}
\newcommand{\therevision}{undefined}
\DeclareRobustCommand{\contestname}{\thecontestname\par\thecontestlocation\unskip, \thecontestdate}
\DeclareRobustCommand{\contest}[3]{
\renewcommand{\thecontestname}{#1}
\renewcommand{\thecontestlocation}{#2}
\renewcommand{\thecontestdate}{#3}
\def\temp{#1}\ifx\temp\empty
\def\temp{#2}\ifx\temp\empty
\def\temp{#3}\ifx\temp\empty
\let\thecontestname\undefined%
\let\thecontestlocation\undefined%
\let\thecontestdate\undefined%
\fi
\fi
\fi
}
\DeclareRobustCommand{\revision}[1]{
\renewcommand{\therevision}{#1}
}
\makeatletter
\renewcommand{\@oddhead}{
\ifdefined\thecontestname
\parbox{\textwidth}{
\sffamily
\begin{center}
\protect\contestname
\\[2pt]
\hrule
\end{center}
}
\fi
}
\renewcommand{\@oddfoot}{
\gdef\problemletter{\if@arabic\arabic{problem}\else\Alph{problem}\fi}
% Revision signature
\ifrevisionsignature%
%\if@revsign%
{\gdef\rsigfooter{, \kw@revision\ \therevision}}%
\else%
{\gdef\rsigfooter{}}%
\fi%
\ifdisplayauthorinfooter%
%\if@newfooter%
{\gdef\thefooter%
{~\quad{\kw@Problem\ \problemletter%
\ifdefined\DivisionNumber{ (Div.~\DivisionNumber)}\fi}%
{\hfill}%
{\kw@ProblemAuthor~\lastproblemauthor}%
{\hfill}%
{\kw@Page\ \thepage\ \kw@of\ \pageref{LastPage}\rsigfooter}\quad~}}%
\else%
\ifdisplaydeveloperinfooter%
{\gdef\thefooter%
{~\quad{\kw@Problem\ \problemletter}%
{\hfill}%
{\kw@ProblemDeveloper~\lastproblemdeveloper}%
{\hfill}%
{\kw@Page\ \thepage\ \kw@of\ \pageref{LastPage}\rsigfooter}\quad~}}%
\else%
{\gdef\thefooter%
{{\hfil}\kw@Page\ \thepage\ \kw@of\ \pageref{LastPage}\rsigfooter\hfil}}%
\fi%
\fi%
\parbox{\textwidth}{
\hrule
\vspace{6pt}
\sffamily
\thefooter
}
}
\makeatother
\headheight=2cm
\headsep=6mm
\hfuzz=0.5pt
\sloppy

View File

@@ -0,0 +1,86 @@
#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
#include "testlib.h"
using namespace std;
int main(int argc, char* argv[]) {
registerGen(argc, argv, 1);
int t = opt<int>(1);
vector<int> a;
vector<vector<int>> b;
if (t == 1) {
a.push_back(1);
b.push_back({ 1, 2, 1 });
}
if (t == 2) {
a.push_back(1);
for (int i = 0; i < 100000; i += 2) {
b.push_back({ 1, 2, 1 });
b.push_back({ 3, 2 });
}
}
if (t == 3) {
a.push_back(1e9);
for (int i = 0; i < 50000; i++)
b.push_back({ 2, i + 1 });
for (int i = 0; i < 50000; i++)
b.push_back({ 3, i + 1 });
}
if (t == 4) {
for (int i = 0; i < 100000; i++)
a.push_back(i + 1);
for (int i = 0; i < 100000; i++)
b.push_back({ 3, i + 1 });
}
if (t == 5) {
for (int i = 0; i < 100000; i++)
a.push_back(i + 1);
for (int i = 0; i < 100000; i++)
b.push_back({ 1, 100000 + i + 1, i + 1 });
}
if (t == 6) {
for (int i = 0; i < 100000; i++)
a.push_back(1e9 - i);
for (int i = 0; i < 50000; i++) {
b.push_back({ 1, i + 1, (int)1e9 - i });
b.push_back({ 3, (int)1e9 - i });
}
}
if (t == 7) {
for (int i = 0; i < 100000; i++)
a.push_back(1e9 - i);
for (int i = 0; i < 100000; i++)
b.push_back({ 3, (int)1e9 - i });
}
if (t == 8) {
for (int i = 0; i < 100000 && b.size() < 100000; i++)
a.push_back(i + 1);
for (int i = 0; i < 100000 && b.size() < 100000; i++)
b.push_back({ 3, (int)1e5 - i });
}
if (t == 9) {
for (int i = 0; i < 100000; i++)
a.push_back(i + 1);
for (int i = 0; i < 100000 && b.size() < 100000; i += 2)
b.push_back({ 3, i + 1 });
for (int i = 0; i < 100000 && b.size() < 100000; i += 2)
b.push_back({ 2, i + 1 });
}
if (t == 10) {
for (int i = 100000; i > 0; i--)
a.push_back(i);
for (int i = 0; i < 100000 && b.size() < 100000; i += 2)
b.push_back({ 3, i + 1 });
for (int i = 0; i < 100000 && b.size() < 100000; i += 2)
b.push_back({ 2, i + 1 });
}
cout << a.size() << ' ' << b.size() << '\n';
for (int i = 0; i < a.size(); i++)
cout << a[i] << " \n"[i + 1 == a.size()];
for (auto i : b) {
for (int j = 0; j < i.size(); j++)
cout << i[j] << " \n"[j + 1 == i.size()];
}
}

Binary file not shown.

View File

@@ -0,0 +1,79 @@
\begin{problem}{${problem.name}}<#--
-->{<#if "stdin" == problem.inputFile><#--
--><#if "russian" == language>стандартный ввод<#--
--><#else>standard input<#--
--></#if><#else>${problem.inputFile}</#if>}<#--
-->{<#if "stdout" == problem.outputFile><#--
--><#if "russian" == language>стандартный вывод<#--
--><#else>standard output<#--
--></#if><#else>${problem.outputFile}</#if>}<#--
--><#assign timeLimit=problem.timeLimit/1000/><#--
--><#if language="russian"><#--
--><#if problem.timeLimit%1000!=0||(10<=timeLimit%100&&timeLimit%100<20)||timeLimit%10=0||5<=timeLimit><#--
-->{${timeLimit?c} секунд}<#--
--><#else><#--
--><#if timeLimit%10=1><#--
-->{${timeLimit?c} секунда}<#--
--><#else><#--
-->{${timeLimit?c} секунды}<#--
--></#if><#--
--></#if><#--
--><#else><#--
-->{${timeLimit?c} second<#if (timeLimit!=1)>s</#if>}<#--
--></#if><#--
--><#assign memoryLimit=problem.memoryLimit/1048576/><#--
--><#if language="russian"><#--
--><#if problem.memoryLimit%1048576==0&&!(10<=memoryLimit%100&&memoryLimit%100<20)&&2<=memoryLimit%10&&memoryLimit%10<5><#--
-->{${memoryLimit?c} мегабайта}
<#else><#--
-->{${memoryLimit?c} мегабайт}
</#if>
<#else><#--
-->{${memoryLimit?c} megabyte<#if (memoryLimit>1)>s</#if>}
</#if>
<#if providedStatementsCommands?? && providedStatementsCommands?size != 0><#--
--><#list providedStatementsCommands as command><#--
-->${command?string}
</#list>
</#if>
${problem.legend}
<#if problem.input?? && (problem.input?length>0)>
\InputFile
${problem.input}
</#if>
<#if problem.output?? && (problem.output?length>0)>
\OutputFile
${problem.output}
</#if>
<#if problem.interaction?? && (problem.interaction?length>0)>
\Interaction
${problem.interaction}
</#if>
<#if problem.scoring?? && (problem.scoring?length>0)>
\Scoring
${problem.scoring}
</#if>
<#if (problem.sampleTests?size>0)>
\Example<#if (problem.sampleTests?size>1)>s</#if>
\begin{example}
<#list problem.sampleTests as test>
\exmpfile{${test.inputFile}}{${test.outputFile}}%
</#list>
\end{example}
</#if>
<#if (problem.notes??) && (problem.notes?length > 0)>
\Note
${problem.notes}
</#if>
\end{problem}

View File

@@ -0,0 +1,53 @@
\documentclass [11pt, a4paper, oneside] {article}
\usepackage [T2A] {fontenc}
\usepackage [utf8] {inputenc}
\usepackage [english, russian] {babel}
\usepackage {amsmath}
\usepackage {amssymb}
\usepackage <#if contest.language?? && contest.language="russian">[russian]<#elseif contest.language?? && contest.language="ukrainian">[ukrainian]</#if>{olymp}
\usepackage {comment}
\usepackage {epigraph}
\usepackage {expdlist}
\usepackage {graphicx}
\usepackage {multirow}
\usepackage {siunitx}
\usepackage {ulem}
%\usepackage {hyperref}
\usepackage {import}
\usepackage {ifpdf}
\usepackage {xparse}
\ifpdf
\DeclareGraphicsRule{*}{mps}{*}{}
\fi
\begin {document}
\contest
{${contest.name!}}%
{${contest.location!}}%
{${contest.date!}}%
\binoppenalty=10000
\relpenalty=10000
\renewcommand{\t}{\texttt}
\renewcommand{\thefootnote}{\fnsymbol{footnote}}
<#if shortProblemTitle?? && shortProblemTitle>
\def\ShortProblemTitle{}
</#if>
<#list statements as statement>
<#if statement.path??>
\graphicspath{{${statement.path}}}
<#if statement.index??>
\def\ProblemIndex{${statement.index}}
</#if>
\import{${statement.path}}{./${statement.file}}
<#else>
\input ${statement.file}
</#if>
</#list>
\end {document}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
7 6
1 2 3 4 5 6 7
1 8 3
2 9
3 3
1 3 9
2 10
3 1

View File

@@ -0,0 +1,3 @@
1 1
1
1 1 1

View File

@@ -0,0 +1,3 @@
1 1
1
2 1

View File

@@ -0,0 +1,4 @@
2 2
1 2
1 3 2
3 4

Binary file not shown.

View File

@@ -0,0 +1,11 @@
\begin{tutorial}{${problem.name}}
<#if providedTutorialCommands?? && providedTutorialCommands?size != 0><#--
--><#list providedTutorialCommands as command><#--
-->${command?string}
</#list>
</#if>
${problem.tutorial}
\end{tutorial}

View File

@@ -0,0 +1,52 @@
#include <bits/stdc++.h>
#include "testlib.h"
using namespace std;
int minN = 1, maxN = 1e5;
int minM = 1, maxM = 1e5;
int minA = 1, maxA = 1e9;
int main(int argc, char* argv[]) {
registerValidation(argc, argv);
int n = inf.readInt(minN, maxN, "n");
inf.readSpace();
int m = inf.readInt(minM, maxM, "m");
inf.readEoln();
set<int> st;
for (int i = 0; i < n; i++) {
int a = inf.readInt(minA, maxA, "a");
if (i == n - 1)
inf.readEoln();
else
inf.readSpace();
st.insert(a);
}
inf.ensuref((int)st.size() == n, "a is unique");
for (int i = 0; i < m; i++) {
int t = inf.readInt(1, 3, "t");
inf.readSpace();
if (t == 1) {
int x = inf.readInt(minA, maxA, "x");
inf.readSpace();
int y = inf.readInt(minA, maxA, "y");
inf.ensuref(st.count(x) == 0, "x is already in list");
inf.ensuref(st.count(y) == 1, "y is not in list");
st.insert(x);
inf.readEoln();
}
if (t == 2) {
int x = inf.readInt(minA, maxA, "x");
inf.ensuref(st.count(x) == 0, "xx is already in list");
st.insert(x);
inf.readEoln();
}
if (t == 3) {
int x = inf.readInt(minA, maxA, "x");
inf.ensuref(st.count(x) == 1, "x is not in list");
st.erase(x);
inf.readEoln();
}
}
inf.readEof();
}

BIN
exam-queue-17/files/val.exe Normal file

Binary file not shown.

168
exam-queue-17/problem.xml Normal file
View File

@@ -0,0 +1,168 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<problem revision="17" short-name="exam-queue" url="https://polygon.codeforces.com/p6Un8qn/valavshonok/exam-queue">
<names>
<name language="russian" value="Очередь за кексами"/>
</names>
<statements>
<statement charset="UTF-8" language="russian" mathjax="true" path="statements/russian/problem.tex" type="application/x-tex"/>
<statement charset="UTF-8" language="russian" mathjax="true" path="statements/.html/russian/problem.html" type="text/html"/>
<statement language="russian" path="statements/.pdf/russian/problem.pdf" type="application/pdf"/>
</statements>
<tutorials>
<tutorial charset="UTF-8" language="russian" mathjax="true" path="statements/russian/tutorial.tex" type="application/x-tex"/>
<tutorial charset="UTF-8" language="russian" mathjax="true" path="statements/.html/russian/tutorial.html" type="text/html"/>
<tutorial language="russian" path="statements/.pdf/russian/tutorial.pdf" type="application/pdf"/>
</tutorials>
<judging cpu-name="Intel(R) Core(TM) i3-8100 CPU @ 3.60GHz" cpu-speed="3600" input-file="" output-file="" run-count="1">
<testset name="tests">
<time-limit>1000</time-limit>
<memory-limit>268435456</memory-limit>
<test-count>51</test-count>
<input-path-pattern>tests/%02d</input-path-pattern>
<answer-path-pattern>tests/%02d.a</answer-path-pattern>
<tests>
<test group="SAMPLES" method="manual" points="0.0" sample="true"/>
<test cmd="gen 1 5 10 5 10 1 100" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 2 5 10 5 10 1 100" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 3 5 10 5 10 1 100" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 4 5 10 5 10 1 100" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 5 5 10 5 10 1 100" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 1 50 100 500 1000 1 1000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 2 50 100 500 1000 1 1000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 3 50 100 500 1000 1 1000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 4 50 100 500 1000 1 1000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 5 50 100 500 1000 1 1000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 1 50000 100000 50000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 2 50000 100000 50000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 3 50000 100000 50000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 4 50000 100000 50000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 5 50000 100000 50000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 6 50000 100000 50000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 7 50000 100000 50000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 8 50000 100000 50000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 9 50000 100000 50000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 10 50000 100000 50000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 1 100000 100000 100000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 2 100000 100000 100000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 3 100000 100000 100000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 4 100000 100000 100000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 5 100000 100000 100000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 6 100000 100000 100000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 7 100000 100000 100000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 8 100000 100000 100000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 9 100000 100000 100000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen 10 100000 100000 100000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen1 1 100000 100000 100000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen1 2 100000 100000 100000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen1 3 100000 100000 100000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen1 4 100000 100000 100000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen1 5 100000 100000 100000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen2 1 100000 100000 100000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen2 2 100000 100000 100000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen2 3 100000 100000 100000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen2 4 100000 100000 100000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="gen2 5 100000 100000 100000 100000 1 1000000000" group="POINTS" method="generated" points="2.0"/>
<test cmd="print 1" group="POINTS" method="generated" points="2.0"/>
<test cmd="print 2" group="POINTS" method="generated" points="2.0"/>
<test cmd="print 3" group="POINTS" method="generated" points="2.0"/>
<test cmd="print 4" group="POINTS" method="generated" points="2.0"/>
<test cmd="print 5" group="POINTS" method="generated" points="2.0"/>
<test cmd="print 6" group="POINTS" method="generated" points="2.0"/>
<test cmd="print 7" group="POINTS" method="generated" points="2.0"/>
<test cmd="print 8" group="POINTS" method="generated" points="2.0"/>
<test cmd="print 9" group="POINTS" method="generated" points="2.0"/>
<test cmd="print 10" group="POINTS" method="generated" points="2.0"/>
</tests>
<groups>
<group feedback-policy="points" name="POINTS" points-policy="each-test">
<dependencies>
<dependency group="SAMPLES"/>
</dependencies>
</group>
<group feedback-policy="points" name="SAMPLES" points="0.0" points-policy="complete-group"/>
</groups>
</testset>
</judging>
<files>
<resources>
<file path="files/olymp.sty"/>
<file path="files/problem.tex"/>
<file path="files/statements.ftl"/>
<file path="files/testlib.h" type="h.g++"/>
<file path="files/tutorial.tex"/>
</resources>
<executables>
<executable>
<source path="files/gen.cpp" type="cpp.gcc14-64-msys2-g++23"/>
<binary path="files/gen.exe" type="exe.win32"/>
</executable>
<executable>
<source path="files/gen1.cpp" type="cpp.gcc14-64-msys2-g++23"/>
<binary path="files/gen1.exe" type="exe.win32"/>
</executable>
<executable>
<source path="files/gen2.cpp" type="cpp.gcc14-64-msys2-g++23"/>
<binary path="files/gen2.exe" type="exe.win32"/>
</executable>
<executable>
<source path="files/print.cpp" type="cpp.gcc14-64-msys2-g++23"/>
<binary path="files/print.exe" type="exe.win32"/>
</executable>
<executable>
<source path="files/val.cpp" type="cpp.gcc14-64-msys2-g++23"/>
<binary path="files/val.exe" type="exe.win32"/>
</executable>
</executables>
</files>
<assets>
<checker name="std::ncmp.cpp" type="testlib">
<source path="files/check.cpp" type="cpp.g++17"/>
<binary path="check.exe" type="exe.win32"/>
<copy path="check.cpp"/>
<testset>
<test-count>0</test-count>
<input-path-pattern>files/tests/checker-tests/%02d</input-path-pattern>
<output-path-pattern>files/tests/checker-tests/%02d.o</output-path-pattern>
<answer-path-pattern>files/tests/checker-tests/%02d.a</answer-path-pattern>
<tests/>
</testset>
</checker>
<validators>
<validator>
<source path="files/val.cpp" type="cpp.gcc14-64-msys2-g++23"/>
<binary path="files/val.exe" type="exe.win32"/>
<testset>
<test-count>4</test-count>
<input-path-pattern>files/tests/validator-tests/%02d</input-path-pattern>
<tests>
<test verdict="valid"/>
<test verdict="invalid"/>
<test verdict="invalid"/>
<test verdict="invalid"/>
</tests>
</testset>
</validator>
</validators>
<solutions>
<solution tag="accepted">
<source path="solutions/nyatl_ok.cpp" type="cpp.gcc14-64-msys2-g++23"/>
<binary path="solutions/nyatl_ok.exe" type="exe.win32"/>
</solution>
<solution tag="main">
<source path="solutions/valavshonok_OK.cpp" type="cpp.gcc14-64-msys2-g++23"/>
<binary path="solutions/valavshonok_OK.exe" type="exe.win32"/>
</solution>
</solutions>
</assets>
<properties>
<property name="tests-wellformed" value="true"/>
</properties>
<stresses>
<stress-count>0</stress-count>
<stress-path-pattern>stresses/%03d</stress-path-pattern>
<list/>
</stresses>
<tags>
<tag value="realization"/>
</tags>
</problem>

View File

@@ -0,0 +1,19 @@
set argumentCount=0
for %%x in (%*) do Set /A argumentCount+=1
if not "%argumentCount%"=="4" pause 0
if "%1"=="" pause 0
if "%2"=="" pause 0
if not exist %1 pause 0
files\val.exe --testset "%~3" --group "%~4" < %1
if errorlevel 1 pause 0
solutions\valavshonok_OK.exe < %1 > output.txt
if errorlevel 1 pause 0
if not exist output.txt pause 0
move output.txt %2
check.exe %1 %2 %2
:start
set error=1
if %errorlevel% equ 0 set error=0
if %errorlevel% equ 7 set error=0
if %error% equ 1 pause 0
:end

View File

@@ -0,0 +1,35 @@
#!/usr/bin/env bash
if [ "$#" -ne "4" ]; then
read
fi
if [ "$1" = "" ]; then
read
fi
if [ "$2" = "" ]; then
read
fi
if [ ! -f "$1" ]; then
read
fi
echo "Running validator"
wine files/towin.exe "$1" | wine files/val.exe --testset "$3" --group "$4"
if [ "$?" -ne "0" ]; then
read
fi
echo "Running solution valavshonok_OK.cpp"
wine solutions/valavshonok_OK.exe < "$1" > output.txt
if [ "$?" -ne "0" ]; then
echo "Solution returned non-zero exit code"
read
fi
if [ ! -f "output.txt" ]; then
echo "Solution didn't produced output"
read
fi
mv output.txt "$2"
echo "Running checker"
wine check.exe "$1" "$2" "$2"
if [ "$?" -ne "0" ] && [ "$?" -ne "7" ]; then
echo "Checker exit code is not equal to 0 and 7"
read
fi

View File

@@ -0,0 +1,22 @@
rem parameter 1 is generator execution command line from the root of the package
rem parameter 2 is test input file path from the root of the package
rem parameter 3 is the test index
if "%~1"=="" pause 0
if "%~2"=="" pause 0
if "%~3"=="" pause 0
del /F /Q "%~2"
if exist tmp-for-generator-execution rd /S /Q tmp-for-generator-execution
md tmp-for-generator-execution
cd tmp-for-generator-execution
%~1
if errorlevel 1 pause 0
if exist "%~3" copy "%~3" "..\%~2"
cd ..
rd /S /Q tmp-for-generator-execution
if not exist "%~2" pause 0

View File

@@ -0,0 +1,50 @@
#!/usr/bin/env bash
if [ "$1" = "" ]
then
echo "First parameter is empty"
read
fi
if [ "$2" = "" ]
then
echo "Second parameter is empty"
read
fi
if [ "$3" = "" ]
then
echo "Third parameter is empty"
read
fi
rm -f "$2"
rm -rf tmp-for-input-generation
mkdir tmp-for-input-generation
cd tmp-for-input-generation
eval $1
if [ "$?" -ne "0" ]
then
echo "Executed "../"$1"", but it returns non-zero exit code"
read
fi
cp "$3" "../$2"
if [ "$?" -ne "0" ]
then
echo "Can't copy $3 to ../$2"
read
fi
if [ ! -f "../$2" ]
then
echo "Can't find ../$2"
read
fi
cd ..
rm -rf tmp-for-input-generation

View File

@@ -0,0 +1,70 @@
@echo off
rem parameter 1 is generator execution command line from the root of the package
rem parameter 2 is test input file path from the root of the package or several paths separated with ":"
rem parameter 3 is the test index or several indices separated with ":"
if "%~1"=="" pause 0
if "%~2"=="" pause 0
if "%~3"=="" pause 0
if exist tmp-for-generator-execution rd /S /Q tmp-for-generator-execution
md tmp-for-generator-execution
cd tmp-for-generator-execution
%~1
if errorlevel 1 pause 0
setlocal ENABLEDELAYEDEXPANSION
set paths=%~2
set indices=%~3
:tokenLoop
if "!paths!" EQU "" goto splitEnd
if "!indices!" EQU "" goto splitEnd
for /f "delims=:" %%a in ("!paths!") do set pathItem=%%a
for /f "delims=:" %%a in ("!indices!") do set indexItem=%%a
if exist "..\!pathItem!" del /F /Q "..\!pathItem!"
set copied=0
if exist "!indexItem!" (
set copied=1
copy "!indexItem!" "..\!pathItem!" > nul
)
if exist "0!indexItem!" (
set copied=1
copy "0!indexItem!" "..\!pathItem!" > nul
)
if exist "00!indexItem!" (
set copied=1
copy "00!indexItem!" "..\!pathItem!" > nul
)
echo %copied%
if "%copied%"=="0" (
echo Unable to find test !indexItem!
pause 0
)
echo Test #!indexItem! has been generated and copied to !pathItem!
:pathsStripLoop
set pathsFirstChar=!paths:~0,1!
set paths=!paths:~1!
if "!paths!" EQU "" goto splitEnd
if "!pathsFirstChar!" NEQ ":" goto pathsStripLoop
:indicesStripLoop
set indicesFirstChar=!indices:~0,1!
set indices=!indices:~1!
if "!indices!" EQU "" goto splitEnd
if "!indicesFirstChar!" NEQ ":" goto indicesStripLoop
goto tokenLoop
:splitEnd
endlocal
cd ..
rd /S /Q tmp-for-generator-execution

View File

@@ -0,0 +1,65 @@
#!/usr/bin/env bash
# parameter 1 is generator execution command line from the root of the package
# parameter 2 is test input file path from the root of the package or several paths separated with ":"
# parameter 3 is the test index or several indices separated with ":"
if [ "$1" = "" ]
then
echo "First parameter is empty"
read
fi
if [ "$2" = "" ]
then
echo "Second parameter is empty"
read
fi
if [ "$3" = "" ]
then
echo "Third parameter is empty"
read
fi
rm -rf tmp-for-input-generation
mkdir tmp-for-input-generation
cd tmp-for-input-generation
eval "$1"
if [ "$?" -ne "0" ]
then
echo "Executed "../"$1"", but it returns non-zero exit code"
read
fi
paths=($(echo "$2" | tr ":" "\n"))
indices=($(echo "$3" | tr ":" "\n"))
for (( i = 0 ; i < ${#paths[@]} ; i++ ))
do
rm -f "../${paths[$i]}"
cp "${indices[$i]}" "../${paths[$i]}" 2> /dev/null ||
cp "0${indices[$i]}" "../${paths[$i]}" 2> /dev/null ||
cp "00${indices[$i]}" "../${paths[$i]}" 2> /dev/null
if [ "$?" -ne "0" ]
then
echo "Can't copy ${indices[$i]} to ../${paths[$i]}"
read
fi
if [ ! -f "../${paths[$i]}" ]
then
echo "Can't find ../${paths[$i]}"
read
fi
echo "Test #${indices[$i]} has been generated and copied to ${paths[$i]}"
done
cd ..
rm -rf tmp-for-input-generation

View File

@@ -0,0 +1,10 @@
rem %1 is generator execution command line from the root of the package
rem %2 is test input file path from the root of the package
rem %3 is the test index
if "%~1"=="" pause 0
if "%~2"=="" pause 0
del /F /Q "%~2"
%~1 > "%~2"
if errorlevel 1 pause 0
if not exist "%~2" pause 0

View File

@@ -0,0 +1,29 @@
#!/usr/bin/env bash
if [ "$1" = "" ]
then
echo "First parameter is empty"
read
fi
if [ "$2" = "" ]
then
echo "Second parameter is empty"
read
fi
rm -f "$2"
eval $1 > $2
if [ "$?" -ne "0" ]
then
echo "Executed $1, but it returns non-zero exit code"
read
fi
if [ ! -f "$2" ]
then
echo "Executed ""$1" > "$2"", but it didn't create file"
read
fi

View File

@@ -0,0 +1,4 @@
echo Running 0 checker test(s)
echo Running 0 checker test(s) 1> checker-tests.log
del /F /Q checker-tests.log
echo Checker test(s) finished

View File

@@ -0,0 +1,5 @@
#!/usr/bin/env bash
echo "Running 0 checker test(s)"
echo "Running 0 checker test(s)" 1> checker-tests.log
rm -f checker-tests.log
echo "Checker test(s) finished"

View File

@@ -0,0 +1,36 @@
echo Running 4 validator test(s)
echo Running 4 validator test(s) 1> validator-tests.log
echo Running test #1 1>> validator-tests.log
echo Validator comment: 1>> validator-tests.log
files\val.exe < files\tests\validator-tests\01 2>> validator-tests.log
if errorlevel 1 (
echo Validator returned non-zero exit code for a valid test 1>> validator-tests.log
echo Validator returned non-zero exit code for a valid test. See validator-tests.log for validator comment
pause 0
)
echo Running test #2 1>> validator-tests.log
echo Validator comment: 1>> validator-tests.log
files\val.exe < files\tests\validator-tests\02 2>> validator-tests.log
if not errorlevel 1 (
echo Validator returned zero exit code for a invalid test 1>> validator-tests.log
echo Validator returned zero exit code for a invalid test. See validator-tests.log for validator comment
pause 0
)
echo Running test #3 1>> validator-tests.log
echo Validator comment: 1>> validator-tests.log
files\val.exe < files\tests\validator-tests\03 2>> validator-tests.log
if not errorlevel 1 (
echo Validator returned zero exit code for a invalid test 1>> validator-tests.log
echo Validator returned zero exit code for a invalid test. See validator-tests.log for validator comment
pause 0
)
echo Running test #4 1>> validator-tests.log
echo Validator comment: 1>> validator-tests.log
files\val.exe < files\tests\validator-tests\04 2>> validator-tests.log
if not errorlevel 1 (
echo Validator returned zero exit code for a invalid test 1>> validator-tests.log
echo Validator returned zero exit code for a invalid test. See validator-tests.log for validator comment
pause 0
)
del /F /Q validator-tests.log
echo Validator test(s) finished

View File

@@ -0,0 +1,37 @@
#!/usr/bin/env bash
echo "Running 4 validator test(s)"
echo "Running 4 validator test(s)" 1> validator-tests.log
echo "Running test #1" 1>> validator-tests.log
echo "Validator comment:" 1>> validator-tests.log
wine files/val.exe < files/tests/validator-tests/01 2>> validator-tests.log
if [ "$?" -ne "0" ]; then
echo "Validator returned non-zero exit code for a valid test" 1>> validator-tests.log
echo "Validator returned non-zero exit code for a valid test. See validator-tests.log for validator comment"
read
fi
echo "Running test #2" 1>> validator-tests.log
echo "Validator comment:" 1>> validator-tests.log
wine files/val.exe < files/tests/validator-tests/02 2>> validator-tests.log
if [ "$?" -eq "0" ]; then
echo "Validator returned zero exit code for a invalid test" 1>> validator-tests.log
echo "Validator returned zero exit code for a invalid test. See validator-tests.log for validator comment"
read
fi
echo "Running test #3" 1>> validator-tests.log
echo "Validator comment:" 1>> validator-tests.log
wine files/val.exe < files/tests/validator-tests/03 2>> validator-tests.log
if [ "$?" -eq "0" ]; then
echo "Validator returned zero exit code for a invalid test" 1>> validator-tests.log
echo "Validator returned zero exit code for a invalid test. See validator-tests.log for validator comment"
read
fi
echo "Running test #4" 1>> validator-tests.log
echo "Validator comment:" 1>> validator-tests.log
wine files/val.exe < files/tests/validator-tests/04 2>> validator-tests.log
if [ "$?" -eq "0" ]; then
echo "Validator returned zero exit code for a invalid test" 1>> validator-tests.log
echo "Validator returned zero exit code for a invalid test. See validator-tests.log for validator comment"
read
fi
rm -f validator-tests.log
echo "Validator test(s) finished"

View File

@@ -0,0 +1,62 @@
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <map>
using namespace std;
#define MAX 101000
int n, k;
int a[MAX];
map<int, int> nxt;
map<int, int> prv;
int main() {
scanf("%d %d", &n, &k);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
for (int i = 1; i < n; i++) {
nxt[a[i]] = a[i + 1];
}
for (int i = 2; i <= n; i++) {
prv[a[i]] = a[i - 1];
}
int last = a[n];
for (int i = 1; i <= k; i++) {
int type;
scanf("%d", &type);
if (type == 1) {
int x, y;
scanf("%d %d", &x, &y);
tie(nxt[x], prv[x], nxt[prv[y]], prv[y]) = {y, prv[y], x, x};
} else if (type == 2) {
int x;
scanf("%d", &x);
nxt[last] = x;
prv[x] = last;
last = x;
} else if (type == 3) {
int x;
scanf("%d", &x);
tie(nxt[prv[x]], prv[nxt[x]]) = {nxt[x], prv[x]};
if (last == x) last = prv[x];
nxt[x] = prv[x] = 0;
}
}
vector<int> ans;
int x = last;
while (x != 0) {
ans.push_back(x);
x = prv[x];
}
printf("%d\n", (int)ans.size());
for (int i = (int)ans.size() - 1; i >= 0; i--) {
printf("%d ", ans[i]);
}
printf("\n");
return 0;
}

View File

@@ -0,0 +1,4 @@
File name: nyatl_ok.cpp
Tag: ACCEPTED
Author: Nyatl
Change time: Mon Apr 07 21:16:54 MSK 2025

Binary file not shown.

View File

@@ -0,0 +1,54 @@
#include <bits/stdc++.h>
using namespace std;
void F() {
int n, m;
cin >> n >> m;
list<int> a;
map<int, list<int>::iterator> mp;
for (int i = 0; i < n; i++) {
int b;
cin >> b;
a.push_back(b);
mp[b] = prev(a.end());
}
while (m--) {
int t;
cin >> t;
if (t == 1) {
int x, y;
cin >> x >> y;
a.insert(mp[y], x);
mp[x] = prev(mp[y]);
}
if (t == 2) {
int x;
cin >> x;
a.push_back(x);
mp[x] = prev(a.end());
}
if (t == 3) {
int x;
cin >> x;
a.erase(mp[x]);
}
}
cout << a.size() << '\n';
for (auto i : a)
cout << i << ' ';
cout << '\n';
}
int main() {
#ifdef KRAKOZAYBRA
FILE* stream;
freopen_s(&stream, "input.txt", "r", stdin);
//freopen_s(&stream, "output.txt", "w", stdout);
#endif
cin.tie(0)->sync_with_stdio(0);
int _t = 1;
//cin >> _t;
while (_t--)
F();
}

View File

@@ -0,0 +1,4 @@
File name: valavshonok_OK.cpp
Tag: MAIN
Author: valavshonok
Change time: Tue Apr 01 00:12:51 MSK 2025

Binary file not shown.

View File

@@ -0,0 +1,8 @@
7 6
1 2 3 4 5 6 7
1 8 3
2 9
3 3
1 3 9
2 10
3 1

View File

@@ -0,0 +1,2 @@
9
2 8 4 5 6 7 3 9 10

View File

@@ -0,0 +1,13 @@
В первой строке заданы два целых числа $n$ и $m$ $(1 \le n, m \le 10^5)$~--- текущее число студентов в очереди и количество изменений.
В следующей строке задается $n$ целых \textbf{различных} чисел $a_1, a_2, \cdots , a_n$ $(1 \le a_i \le 10^9)$, где $a_i$~--- номер студента, который стоит на $i$-й позиции в очереди.
В следующих $m$ строках идет описание запросов изменения очереди.
В каждой строке в зависимости от типа запроса задается два или три числа. Первое число $t_j$ $(1 \le t_j \le 3)$~--- тип события, которое произошло в $j$-ю минуту.
Если $t_j = \textbf{1}$, то в строке задается еще 2 числа $x$ $(1 \le x_j \le 10^9)$ и $y$ $(1 \le y_j \le 10^9)$~--- номер студента, который пришел, и номер студента, перед которым он встанет в очереди. Гарантируется, что студент с номером $x$ ещё не занял очередь, а студент с номером $y$ уже стоит в ней.
Если $t_j = \textbf{2}$, то в строке задается еще 1 число $x$ $(1 \le x_j \le 10^9)$~--- номер студента, который пришел и встал в конец очереди. Гарантируется, что студент с номером $x$ ещё не занял очередь.
Если $t_j = \textbf{3}$, то в строке задается еще 1 число $x$ $(1 \le x_j \le 10^9)$~--- номер студента, который ушел из очереди. Гарантируется, что студент с номером $x$ стоит в очереди.

View File

@@ -0,0 +1,16 @@
В честь юбилея ректорат ЮФУ решил запустить акцию <<Сто и десять кексов>>. В каждом корпусе университета открылась лавка с кексами, в которой каждый студент может получить бесплатные кексы.
Не прошло и пары минут после открытия, как к лавкам набежали студенты и образовалось много очередей. Но самая большая очередь образовалась в главном корпусе ЮФУ. Изначально в этой очереди стояло $n$ студентов, но потом в течение следующих $m$ минут какие-то студенты приходили и вставали в очередь, а какие-то уходили.
За каждым студентом закреплен номер его зачетной книжки, будем называть это число номером студента. У каждого студента будет уникальный номер, по которому можно однозначно его идентифицировать. Будем считать, что каждую минуту происходило одно из следующих событий:
\begin{enumerate}
\item Студент с номером $x$ пришел и встал перед студентом с номером $y$;
\item Студент с номером $x$ пришел и встал в конец очереди;
\item Студент с номером $x$ ушел из очереди; возможно, он потом вернется.
\end{enumerate}
Аналитикам стало интересно, а какой будет очередь после $m$ минут?
Помогите им и сообщите конечное состояние очереди.

View File

@@ -0,0 +1 @@
Очередь за кексами

View File

@@ -0,0 +1,31 @@
Изначально очередь выглядит следующим образом:
\includegraphics{o1.png}
В первую минуту приходит студент с номером 8 и встает перед студентом с номером 3.
\includegraphics{o2.png}
Потом студент с номером 9 встает в конец очереди.
\includegraphics{o3.png}
Студент с номером 3 уходит из очереди.
\includegraphics{o4.png}
Потом он возвращается и становится перед студентом с номером 9.
\includegraphics{o5.png}
После в конец очереди становится студент с номером 10.
\includegraphics{o6.png}
И студент с номером 1 уходит из очереди.
\includegraphics{o7.png}
После $m$ событий очередь имеет следующий вид:
\includegraphics{o8.png}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -0,0 +1,3 @@
В первой строке выведите одно число $|a|$~--- длину очереди после выполнения всех запросов изменения.
В следующей строке выведите $|a|$ чисел $a_1, a_2, \cdots , a_{|a|}$, где $a_i$~--- номер студента, который стоит на $i$-й позиции в очереди.

View File

@@ -0,0 +1,15 @@
Давайте просто промоделируем все действия.
Заведем список элементов, а также сохраним по ключу $x$ указатель на элемент списка. Мы можем это сделать, так как все элементы различны. Например, в С++ можно просто завести коллекцию list<int>, а также map<int, list<int>::iterator> или реализовать свой список.
Теперь мы можем легко обрабатывать все запросы, а в конце просто выведем весь список.
Запрос 1-го типа можно обработать так: просто берем по ключу указатель на нужный элемент и вставляем перед ним другой элемент, останется только по ключу $x$ записать указатель на новый элемент.
Запрос 2-го типа~--- просто добавить в список элемент в конец и сохранить на него указатель.
Запрос 3-го типа~--- удаляем из списка элемент по его указателю.
В конце просто выводим массив.
Итоговая сложность $O(mlog(n))$

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -0,0 +1,318 @@
.problem-statement {
margin: 0.5em auto 2em auto;
font-family: verdana,serif;
line-height: 1.5em;
font-size: 14px;
max-width: 1024px;
}
.problem-statement .epigraph {
margin-left: 67%;
width: 33%;
}
.problem-statement .epigraph-text {
}
.problem-statement .epigraph-source {
border-top: 1px solid #888;
text-align: right;
}
.problem-statement .lstlisting {
padding: 0.5em;
background-color: #f2f2f2;
}
.problem-statement .tex-tabular {
margin: 1em 0;
border-collapse: collapse;
border-spacing: 0;
}
.problem-statement .tex-tabular td {
padding: 0.15em 0.7em;
}
.problem-statement .tex-tabular .tex-tabular-border-left {
border-left: 1px solid;
}
.problem-statement .tex-tabular .tex-tabular-border-right {
border-right: 1px solid;
}
.problem-statement .tex-tabular .tex-tabular-border-top {
border-top: 1px solid;
}
.problem-statement .tex-tabular .tex-tabular-border-bottom {
border-bottom: 1px solid;
}
.problem-statement .tex-tabular .tex-tabular-text-align-left {
text-align: left;
}
.problem-statement .tex-tabular .tex-tabular-text-align-center {
text-align: center;
}
.problem-statement .tex-tabular .tex-tabular-text-align-right {
text-align: right;
}
.problem-statement p {
margin: 0 0 1em 0;
}
.problem-statement p a, .problem-statement ul a, .problem-statement ol a, .problem-statement td a {
margin: 0;
}
.problem-statement .header {
margin-bottom: 1em;
text-align: center;
}
.problem-statement .header .title {
font-size: 150%;
margin-bottom: 0.25em;
}
.problem-statement .header .title {
font-size: 150%;
font-family: arial, serif;
}
.problem-statement ul {
list-style: disc outside;
margin: 0 0 1em 0;
}
.problem-statement ol {
list-style: decimal outside;
margin: 0 0 1em 0;
}
.problem-statement li {
line-height: 1.5em;
margin-left: 3em;
}
.problem-statement .property-title {
display: inline;
}
.problem-statement .property-title:after {
content: ": ";
}
.problem-statement .time-limit, .problem-statement .memory-limit, .problem-statement .input-file, .problem-statement .output-file {
margin: 0 auto;
}
.problem-statement .legend {
margin-bottom: 1em;
}
.problem-statement .tutorial {
margin-bottom: 1em;
}
.problem-statement .section-title {
font-family: arial, serif;
font-size: 115%;
font-weight: bold;
}
.problem-statement .input-specification,
.problem-statement .output-specification,
.problem-statement .sample-tests,
.problem-statement .author,
.problem-statement .resource,
.problem-statement .date {
/*margin-bottom: 1em;*/
}
.problem-statement .output-specification {
margin-bottom: 1em;
}
.problem-statement .sample-tests .sample-test {
}
.problem-statement .sample-tests .input, .problem-statement .sample-tests .output {
border: 1px solid #888;
}
.problem-statement .sample-tests .output {
margin-bottom: 1em;
position: relative;
top: -1px;
}
.problem-statement .sample-tests pre {
line-height: 1.25em;
padding: 0.25em;
margin: 0;
background-color: #efefef;
}
.problem-statement .sample-tests .title {
font-family: arial, serif;
padding: 0.25em;
border-bottom: 1px solid #888;
text-transform: lowercase;
font-weight: bold;
}
.problem-statement .tex-formula {
vertical-align: middle;
margin: 0;
border:medium none;
position: relative;
bottom: 2px;
}
.problem-statement .tex-span {
font-size: 125%;
font-family: times new roman, serif;
white-space: nowrap;
}
.problem-statement .tex-font-size-tiny {
font-size: 70%;
}
.problem-statement .tex-font-size-script {
font-size: 75%;
}
.problem-statement .tex-font-size-footnotes {
font-size: 85%;
}
.problem-statement .tex-font-size-small {
font-size: 85%;
}
.problem-statement .tex-font-size-normal {
font-size: 100%;
}
.problem-statement .tex-font-size-large-1 {
font-size: 115%;
}
.problem-statement .tex-font-size-large-2 {
font-size: 130%;
}
.problem-statement .tex-font-size-large-3 {
font-size: 145%;
}
.problem-statement .tex-font-size-huge-1 {
font-size: 175%;
}
.problem-statement .tex-font-size-huge-2 {
font-size: 200%;
}
.problem-statement .tex-font-style-rm {
}
.problem-statement .tex-font-style-striked {
text-decoration: line-through;
}
.problem-statement .tex-font-style-underline {
text-decoration: underline;
}
.problem-statement .tex-font-style-sf {
font-family: arial, serif;
}
.problem-statement .tex-font-style-tt {
font-size: 110%;
font-family: courier new, serif;
}
.problem-statement .tex-font-style-md {
}
.problem-statement .tex-font-style-bf {
font-weight: bold;
}
.problem-statement .tex-font-style-up {
}
.problem-statement .tex-font-style-it {
font-style: italic;
}
.problem-statement .tex-font-style-sl {
font-style: italic;
}
.problem-statement .tex-font-style-sc {
text-transform: uppercase;
}
.problem-statement .tex-graphics {
max-width: 95%;
display: block;
}
.problem-statement .tex-tabular .tex-graphics {
max-width: 100%;
}
.problem-statement .input-output-copier {
font-size: 0.75rem;
float: right;
color: #888;
padding: 3px;
cursor: pointer;
border: 1px solid rgb(185, 185, 185);
line-height: 0.8rem;
text-transform: none;
}
.problem-statement .input-output-copier:hover {
background-color: #def;
}
.problem-statement .test-example-line-even {
background-color: #E0E0E0;
}
.statement-footnote {
font-size: 85%;
position: relative;
}
.statement-footnote::before {
content: "";
position: absolute;
top: -2px;
width: 25%;
border-top: 1px solid #888;
}
.statement-footnote p {
margin-bottom: 0.5em;
}
.statement-footnote p:last-child {
margin-bottom: 1em;
}
.problem-statement .header .input-standard,
.problem-statement .header .output-standard {
display: none;
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,17 @@
<HTML><HEAD><META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<META content="no-cache" http-equiv="pragma">
<META content="-1" http-equiv="expires">
<META content="text/html;charset=UTF-8" http-equiv="content-type">
<LINK href="problem-statement.css" rel="stylesheet" type="text/css">
<TITLE>Очередь за кексами</TITLE>
<SCRIPT type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {inlineMath: [['$$$','$$$']], displayMath: [['$$$$$$','$$$$$$']]}
});
</SCRIPT>
<SCRIPT async="" src="https://polygon.codeforces.com/lib/MathJax/MathJax.js?config=TeX-MML-AM_CHTML" type="text/javascript">
</SCRIPT>
</HEAD><BODY>
<DIV class="problem-statement"><DIV class="header"><DIV class="title">Очередь за кексами</DIV></DIV><DIV class="tutorial"><P>Давайте просто промоделируем все действия.</P><P>Заведем список элементов, а также сохраним по ключу $$$x$$$ указатель на элемент списка. Мы можем это сделать, так как все элементы различны. Например, в С++ можно просто завести коллекцию list&lt;int&gt;, а также map&lt;int, list&lt;int&gt;::iterator&gt; или реализовать свой список.</P><P>Теперь мы можем легко обрабатывать все запросы, а в конце просто выведем весь список.</P><P>Запрос 1-го типа можно обработать так: просто берем по ключу указатель на нужный элемент и вставляем перед ним другой элемент, останется только по ключу $$$x$$$ записать указатель на новый элемент.</P><P>Запрос 2-го типа&nbsp;&mdash; просто добавить в список элемент в конец и сохранить на него указатель.</P><P>Запрос 3-го типа&nbsp;&mdash; удаляем из списка элемент по его указателю.</P><P>В конце просто выводим массив.</P><P>Итоговая сложность $$$O(mlog(n))$$$</P></DIV></DIV>
</BODY></HTML>

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,8 @@
7 6
1 2 3 4 5 6 7
1 8 3
2 9
3 3
1 3 9
2 10
3 1

View File

@@ -0,0 +1,2 @@
9
2 8 4 5 6 7 3 9 10

View File

@@ -0,0 +1,8 @@
MU<EFBFBD>7 6
1 2 3 4 5 6 7
1 8 3
2 9
3 3
1 3 9
2 10
3 1

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,81 @@
\begin{problem}{Очередь за кексами}{стандартный ввод}{стандартный вывод}{1 секунда}{256 мегабайт}
В честь юбилея ректорат ЮФУ решил запустить акцию <<Сто и десять кексов>>. В каждом корпусе университета открылась лавка с кексами, в которой каждый студент может получить бесплатные кексы.
Не прошло и пары минут после открытия, как к лавкам набежали студенты и образовалось много очередей. Но самая большая очередь образовалась в главном корпусе ЮФУ. Изначально в этой очереди стояло $n$ студентов, но потом в течение следующих $m$ минут какие-то студенты приходили и вставали в очередь, а какие-то уходили.
За каждым студентом закреплен номер его зачетной книжки, будем называть это число номером студента. У каждого студента будет уникальный номер, по которому можно однозначно его идентифицировать. Будем считать, что каждую минуту происходило одно из следующих событий:
\begin{enumerate}
\item Студент с номером $x$ пришел и встал перед студентом с номером $y$;
\item Студент с номером $x$ пришел и встал в конец очереди;
\item Студент с номером $x$ ушел из очереди; возможно, он потом вернется.
\end{enumerate}
Аналитикам стало интересно, а какой будет очередь после $m$ минут?
Помогите им и сообщите конечное состояние очереди.
\InputFile
В первой строке заданы два целых числа $n$ и $m$ $(1 \le n, m \le 10^5)$~--- текущее число студентов в очереди и количество изменений.
В следующей строке задается $n$ целых \textbf{различных} чисел $a_1, a_2, \cdots , a_n$ $(1 \le a_i \le 10^9)$, где $a_i$~--- номер студента, который стоит на $i$-й позиции в очереди.
В следующих $m$ строках идет описание запросов изменения очереди.
В каждой строке в зависимости от типа запроса задается два или три числа. Первое число $t_j$ $(1 \le t_j \le 3)$~--- тип события, которое произошло в $j$-ю минуту.
Если $t_j = \textbf{1}$, то в строке задается еще 2 числа $x$ $(1 \le x_j \le 10^9)$ и $y$ $(1 \le y_j \le 10^9)$~--- номер студента, который пришел, и номер студента, перед которым он встанет в очереди. Гарантируется, что студент с номером $x$ ещё не занял очередь, а студент с номером $y$ уже стоит в ней.
Если $t_j = \textbf{2}$, то в строке задается еще 1 число $x$ $(1 \le x_j \le 10^9)$~--- номер студента, который пришел и встал в конец очереди. Гарантируется, что студент с номером $x$ ещё не занял очередь.
Если $t_j = \textbf{3}$, то в строке задается еще 1 число $x$ $(1 \le x_j \le 10^9)$~--- номер студента, который ушел из очереди. Гарантируется, что студент с номером $x$ стоит в очереди.
\OutputFile
В первой строке выведите одно число $|a|$~--- длину очереди после выполнения всех запросов изменения.
В следующей строке выведите $|a|$ чисел $a_1, a_2, \cdots , a_{|a|}$, где $a_i$~--- номер студента, который стоит на $i$-й позиции в очереди.
\Example
\begin{example}
\exmpfile{example.01}{example.01.a}%
\end{example}
\Note
Изначально очередь выглядит следующим образом:
\includegraphics{o1.png}
В первую минуту приходит студент с номером 8 и встает перед студентом с номером 3.
\includegraphics{o2.png}
Потом студент с номером 9 встает в конец очереди.
\includegraphics{o3.png}
Студент с номером 3 уходит из очереди.
\includegraphics{o4.png}
Потом он возвращается и становится перед студентом с номером 9.
\includegraphics{o5.png}
После в конец очереди становится студент с номером 10.
\includegraphics{o6.png}
И студент с номером 1 уходит из очереди.
\includegraphics{o7.png}
После $m$ событий очередь имеет следующий вид:
\includegraphics{o8.png}
\end{problem}

View File

@@ -0,0 +1,19 @@
\begin{tutorial}{Очередь за кексами}
Давайте просто промоделируем все действия.
Заведем список элементов, а также сохраним по ключу $x$ указатель на элемент списка. Мы можем это сделать, так как все элементы различны. Например, в С++ можно просто завести коллекцию list<int>, а также map<int, list<int>::iterator> или реализовать свой список.
Теперь мы можем легко обрабатывать все запросы, а в конце просто выведем весь список.
Запрос 1-го типа можно обработать так: просто берем по ключу указатель на нужный элемент и вставляем перед ним другой элемент, останется только по ключу $x$ записать указатель на новый элемент.
Запрос 2-го типа~--- просто добавить в список элемент в конец и сохранить на него указатель.
Запрос 3-го типа~--- удаляем из списка элемент по его указателю.
В конце просто выводим массив.
Итоговая сложность $O(mlog(n))$
\end{tutorial}

1
exam-queue-17/tags Normal file
View File

@@ -0,0 +1 @@
realization

8
exam-queue-17/tests/01 Normal file
View File

@@ -0,0 +1,8 @@
7 6
1 2 3 4 5 6 7
1 8 3
2 9
3 3
1 3 9
2 10
3 1

103
exam-queue-17/wipe.bat Normal file
View File

@@ -0,0 +1,103 @@
rem *** tests ***
del tests\01.a
del tests\02
del tests\02.a
del tests\03
del tests\03.a
del tests\04
del tests\04.a
del tests\05
del tests\05.a
del tests\06
del tests\06.a
del tests\07
del tests\07.a
del tests\08
del tests\08.a
del tests\09
del tests\09.a
del tests\10
del tests\10.a
del tests\11
del tests\11.a
del tests\12
del tests\12.a
del tests\13
del tests\13.a
del tests\14
del tests\14.a
del tests\15
del tests\15.a
del tests\16
del tests\16.a
del tests\17
del tests\17.a
del tests\18
del tests\18.a
del tests\19
del tests\19.a
del tests\20
del tests\20.a
del tests\21
del tests\21.a
del tests\22
del tests\22.a
del tests\23
del tests\23.a
del tests\24
del tests\24.a
del tests\25
del tests\25.a
del tests\26
del tests\26.a
del tests\27
del tests\27.a
del tests\28
del tests\28.a
del tests\29
del tests\29.a
del tests\30
del tests\30.a
del tests\31
del tests\31.a
del tests\32
del tests\32.a
del tests\33
del tests\33.a
del tests\34
del tests\34.a
del tests\35
del tests\35.a
del tests\36
del tests\36.a
del tests\37
del tests\37.a
del tests\38
del tests\38.a
del tests\39
del tests\39.a
del tests\40
del tests\40.a
del tests\41
del tests\41.a
del tests\42
del tests\42.a
del tests\43
del tests\43.a
del tests\44
del tests\44.a
del tests\45
del tests\45.a
del tests\46
del tests\46.a
del tests\47
del tests\47.a
del tests\48
del tests\48.a
del tests\49
del tests\49.a
del tests\50
del tests\50.a
del tests\51
del tests\51.a

104
exam-queue-17/wipe.sh Normal file
View File

@@ -0,0 +1,104 @@
#!/usr/bin/env bash
# *** tests ***
rm -f tests/01.a
rm -f tests/02
rm -f tests/02.a
rm -f tests/03
rm -f tests/03.a
rm -f tests/04
rm -f tests/04.a
rm -f tests/05
rm -f tests/05.a
rm -f tests/06
rm -f tests/06.a
rm -f tests/07
rm -f tests/07.a
rm -f tests/08
rm -f tests/08.a
rm -f tests/09
rm -f tests/09.a
rm -f tests/10
rm -f tests/10.a
rm -f tests/11
rm -f tests/11.a
rm -f tests/12
rm -f tests/12.a
rm -f tests/13
rm -f tests/13.a
rm -f tests/14
rm -f tests/14.a
rm -f tests/15
rm -f tests/15.a
rm -f tests/16
rm -f tests/16.a
rm -f tests/17
rm -f tests/17.a
rm -f tests/18
rm -f tests/18.a
rm -f tests/19
rm -f tests/19.a
rm -f tests/20
rm -f tests/20.a
rm -f tests/21
rm -f tests/21.a
rm -f tests/22
rm -f tests/22.a
rm -f tests/23
rm -f tests/23.a
rm -f tests/24
rm -f tests/24.a
rm -f tests/25
rm -f tests/25.a
rm -f tests/26
rm -f tests/26.a
rm -f tests/27
rm -f tests/27.a
rm -f tests/28
rm -f tests/28.a
rm -f tests/29
rm -f tests/29.a
rm -f tests/30
rm -f tests/30.a
rm -f tests/31
rm -f tests/31.a
rm -f tests/32
rm -f tests/32.a
rm -f tests/33
rm -f tests/33.a
rm -f tests/34
rm -f tests/34.a
rm -f tests/35
rm -f tests/35.a
rm -f tests/36
rm -f tests/36.a
rm -f tests/37
rm -f tests/37.a
rm -f tests/38
rm -f tests/38.a
rm -f tests/39
rm -f tests/39.a
rm -f tests/40
rm -f tests/40.a
rm -f tests/41
rm -f tests/41.a
rm -f tests/42
rm -f tests/42.a
rm -f tests/43
rm -f tests/43.a
rm -f tests/44
rm -f tests/44.a
rm -f tests/45
rm -f tests/45.a
rm -f tests/46
rm -f tests/46.a
rm -f tests/47
rm -f tests/47.a
rm -f tests/48
rm -f tests/48.a
rm -f tests/49
rm -f tests/49.a
rm -f tests/50
rm -f tests/50.a
rm -f tests/51
rm -f tests/51.a

View File

@@ -3,6 +3,7 @@ namespace LiquidCode.Tester.Common.Models;
public class ProblemPackage
{
public string WorkingDirectory { get; set; } = string.Empty;
public string? ExtractionRoot { get; set; }
public List<TestCase> TestCases { get; set; } = new();
public string? CheckerPath { get; set; }
public int DefaultTimeLimit { get; set; } = 2000; // milliseconds

View File

@@ -7,5 +7,7 @@ public record SubmitForTesterModel(
string LanguageVersion,
string SourceCode,
string PackageUrl,
string CallbackUrl
string CallbackUrl,
int? TimeLimitMs = null,
int? MemoryLimitMb = null
);

View File

@@ -30,11 +30,11 @@ public class TesterController : ControllerBase
try
{
// Download the package
var packagePath = await _packageDownloadService.DownloadPackageAsync(request.PackageUrl);
// Download the package or use cached version if available
var packagePath = await _packageDownloadService.GetOrDownloadPackageAsync(request.MissionId, request.PackageUrl);
// Send to appropriate worker based on language
await _workerClientService.SendToWorkerAsync(request, packagePath);
await _workerClientService.SendToWorkerAsync(request, packagePath, deletePackageAfterSend: false);
return Accepted(new { message = "Submit accepted for testing", submitId = request.Id });
}
@@ -82,11 +82,13 @@ public class TesterController : ControllerBase
LanguageVersion: request.LanguageVersion,
SourceCode: request.SourceCode,
PackageUrl: packagePath, // Use local path instead of URL
CallbackUrl: request.CallbackUrl
CallbackUrl: request.CallbackUrl,
TimeLimitMs: request.TimeLimitMs,
MemoryLimitMb: request.MemoryLimitMb
);
// Send to appropriate worker based on language
await _workerClientService.SendToWorkerAsync(submitModel, packagePath);
await _workerClientService.SendToWorkerAsync(submitModel, packagePath, deletePackageAfterSend: true);
return Accepted(new { message = "Submit accepted for testing", submitId = request.Id });
}

View File

@@ -9,4 +9,14 @@ public class LocalSubmitModel
public string SourceCode { get; set; } = string.Empty;
public string CallbackUrl { get; set; } = string.Empty;
public IFormFile? Package { get; set; }
/// <summary>
/// Optional time limit override in milliseconds (for testing purposes)
/// </summary>
public int? TimeLimitMs { get; set; }
/// <summary>
/// Optional memory limit override in megabytes (for testing purposes)
/// </summary>
public int? MemoryLimitMb { get; set; }
}

View File

@@ -10,6 +10,7 @@ builder.Services.AddOpenApi();
// Add HttpClient
builder.Services.AddHttpClient();
builder.Services.AddMemoryCache();
// Register application services
builder.Services.AddSingleton<IPackageDownloadService, PackageDownloadService>();
@@ -18,7 +19,7 @@ builder.Services.AddSingleton<IWorkerClientService, WorkerClientService>();
var app = builder.Build();
// Configure the HTTP request pipeline
if (app.Environment.IsDevelopment())
//if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();

Some files were not shown because too many files have changed in this diff Show More