Compare commits

...

14 Commits

Author SHA1 Message Date
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
69829569bb update polygon package parsing & testing 2025-10-28 22:01:35 +04:00
131 changed files with 14684 additions and 298 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

@@ -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

@@ -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 });
}
@@ -86,7 +86,7 @@ public class TesterController : ControllerBase
);
// 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

@@ -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();

View File

@@ -3,9 +3,10 @@ namespace LiquidCode.Tester.Gateway.Services;
public interface IPackageDownloadService
{
/// <summary>
/// Downloads a package from the specified URL
/// Retrieves a cached package for the mission or downloads it if missing.
/// </summary>
/// <param name="packageUrl">URL to download the package from</param>
/// <returns>Path to the downloaded package file</returns>
Task<string> DownloadPackageAsync(string packageUrl);
/// <param name="missionId">Unique mission identifier used as cache key.</param>
/// <param name="packageUrl">URL to download the package from when cache is cold.</param>
/// <returns>Path to the cached or downloaded package file.</returns>
Task<string> GetOrDownloadPackageAsync(long missionId, string packageUrl);
}

View File

@@ -8,6 +8,7 @@ public interface IWorkerClientService
/// Sends a submit to the appropriate worker based on the language
/// </summary>
/// <param name="submit">Submit data</param>
/// <param name="packagePath">Local path to the downloaded package</param>
Task SendToWorkerAsync(SubmitForTesterModel submit, string packagePath);
/// <param name="packagePath">Local path to the package that will be streamed to the worker</param>
/// <param name="deletePackageAfterSend">Indicates whether the package file should be removed after upload</param>
Task SendToWorkerAsync(SubmitForTesterModel submit, string packagePath, bool deletePackageAfterSend);
}

View File

@@ -1,3 +1,6 @@
using System.Collections.Concurrent;
using Microsoft.Extensions.Caching.Memory;
namespace LiquidCode.Tester.Gateway.Services;
public class PackageDownloadService : IPackageDownloadService
@@ -5,14 +8,20 @@ public class PackageDownloadService : IPackageDownloadService
private readonly IHttpClientFactory _httpClientFactory;
private readonly ILogger<PackageDownloadService> _logger;
private readonly string _downloadDirectory;
private readonly IMemoryCache _memoryCache;
private readonly ConcurrentDictionary<long, SemaphoreSlim> _locks = new();
private sealed record PackageCacheEntry(string FilePath);
public PackageDownloadService(
IHttpClientFactory httpClientFactory,
ILogger<PackageDownloadService> logger,
IConfiguration configuration)
IConfiguration configuration,
IMemoryCache memoryCache)
{
_httpClientFactory = httpClientFactory;
_logger = logger;
_memoryCache = memoryCache;
_downloadDirectory = configuration["PackageDownloadDirectory"] ?? Path.Combine(Path.GetTempPath(), "packages");
if (!Directory.Exists(_downloadDirectory))
@@ -21,12 +30,25 @@ public class PackageDownloadService : IPackageDownloadService
}
}
public async Task<string> DownloadPackageAsync(string packageUrl)
public async Task<string> GetOrDownloadPackageAsync(long missionId, string packageUrl)
{
_logger.LogInformation("Downloading package from {Url}", packageUrl);
if (TryGetCachedFile(missionId, out var cachedFile))
{
return cachedFile;
}
var missionLock = _locks.GetOrAdd(missionId, _ => new SemaphoreSlim(1, 1));
await missionLock.WaitAsync();
try
{
if (TryGetCachedFile(missionId, out cachedFile))
{
return cachedFile;
}
_logger.LogInformation("Downloading package for mission {MissionId} from {Url}", missionId, packageUrl);
var httpClient = _httpClientFactory.CreateClient();
var response = await httpClient.GetAsync(packageUrl);
response.EnsureSuccessStatusCode();
@@ -34,16 +56,92 @@ public class PackageDownloadService : IPackageDownloadService
var fileName = $"package_{Guid.NewGuid()}.zip";
var filePath = Path.Combine(_downloadDirectory, fileName);
await using var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None);
await response.Content.CopyToAsync(fileStream);
try
{
await using var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None);
await response.Content.CopyToAsync(fileStream);
}
catch
{
if (File.Exists(filePath))
{
try
{
File.Delete(filePath);
}
catch (Exception cleanupEx)
{
_logger.LogWarning(cleanupEx, "Failed to clean up temporary file {Path} after download error", filePath);
}
}
throw;
}
CacheFile(missionId, filePath);
_logger.LogInformation("Package downloaded and cached for mission {MissionId} at {Path}", missionId, filePath);
_logger.LogInformation("Package downloaded successfully to {Path}", filePath);
return filePath;
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to download package from {Url}", packageUrl);
_logger.LogError(ex, "Failed to download package for mission {MissionId} from {Url}", missionId, packageUrl);
throw;
}
finally
{
missionLock.Release();
}
}
private bool TryGetCachedFile(long missionId, out string filePath)
{
if (_memoryCache.TryGetValue(missionId, out PackageCacheEntry? cacheEntry))
{
if (cacheEntry is not null && File.Exists(cacheEntry.FilePath))
{
filePath = cacheEntry.FilePath;
_logger.LogInformation("Using cached package for mission {MissionId} from {Path}", missionId, filePath);
return true;
}
_memoryCache.Remove(missionId);
}
filePath = string.Empty;
return false;
}
private void CacheFile(long missionId, string filePath)
{
var cacheEntry = new PackageCacheEntry(filePath);
var options = new MemoryCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1)
};
options.RegisterPostEvictionCallback((_, value, _, _) =>
{
if (value is not PackageCacheEntry entry)
{
return;
}
try
{
if (File.Exists(entry.FilePath))
{
File.Delete(entry.FilePath);
_logger.LogInformation("Removed cached package file {Path} after expiration", entry.FilePath);
}
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to delete cached package file {Path} during eviction", entry.FilePath);
}
});
_memoryCache.Set(missionId, cacheEntry, options);
}
}

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