| # | Bài tập | Điểm | Thời gian: | Giới hạn bộ nhớ |
|---|---|---|---|---|
| 1 | IOI 2021 - Distributing Candies | 100 (p) | 4.0s | 2G |
| 2 | IOI 2021 - Keys | 100 (p) | 2.0s | 2G |
| 3 | IOI 2021 - Fountain Parks | 100 (p) | 3.0s | 2G |
Cô Khong đang chuẩn bị \(n\) hộp kẹo cho học sinh của một ngôi trường gần nhà. Các hộp được đánh số từ \(0\) đến \(n-1\) và ban đầu đều rỗng. Hộp \(i\) (\(0 \le i \le n-1\)) có sức chứa \(c[i]\) viên kẹo.
Cô Khong dành \(q\) ngày để chuẩn bị các hộp kẹo. Vào ngày \(j\) (\(0 \le j \le q-1\)), cô thực hiện một thao tác được xác định bởi ba số nguyên \(l[j]\), \(r[j]\) và \(v[j]\), trong đó \(0 \le l[j] \le r[j] \le n-1\) và \(v[j] \ne 0\). Với mỗi hộp \(k\) thỏa mãn \(l[j] \le k \le r[j]\):
Nhiệm vụ của bạn là xác định số kẹo trong mỗi hộp sau \(q\) ngày.
Bạn cần cài đặt hàm sau:
std::vector<int> distribute_candies(std::vector<int> c, std::vector<int> l,
std::vector<int> r, std::vector<int> v);
c: mảng độ dài \(n\). Với \(0 \le i \le n-1\), \(c[i]\) là sức chứa của hộp \(i\).l, r, v: ba mảng độ dài \(q\). Vào ngày \(j\), với \(0 \le j \le q-1\), cô Khong thực hiện thao tác được xác định bởi \(l[j]\), \(r[j]\) và \(v[j]\) như mô tả ở trên.Trình chấm mẫu đọc dữ liệu theo định dạng sau:
Trình chấm mẫu in câu trả lời theo định dạng sau:
| Nhóm | Điểm | Ràng buộc bổ sung |
|---|---|---|
| 1 | 3 | \(n, q \le 2000\). |
| 2 | 8 | \(v[j] > 0\) với mọi \(0 \le j \le q-1\). |
| 3 | 27 | \(c[0] = c[1] = \cdots = c[n-1]\). |
| 4 | 29 | \(l[j] = 0\) và \(r[j] = n-1\) với mọi \(0 \le j \le q-1\). |
| 5 | 33 | Không có ràng buộc bổ sung. |
Ví dụ 1
distribute_candies([10, 15, 13], [0, 0], [2, 1], [20, -11])
[0, 4, 13]
Hộp \(0\) có sức chứa \(10\) viên kẹo, hộp \(1\) có sức chứa \(15\) viên kẹo và hộp \(2\) có sức chứa \(13\) viên kẹo.
Kết thúc ngày \(0\), hộp \(0\) có \(\min(c[0], 0+v[0]) = 10\) viên kẹo, hộp \(1\) có \(\min(c[1], 0+v[0]) = 15\) viên kẹo và hộp \(2\) có \(\min(c[2], 0+v[0]) = 13\) viên kẹo.
Kết thúc ngày \(1\), hộp \(0\) có \(\max(0, 10+v[1]) = 0\) viên kẹo và hộp \(1\) có \(\max(0, 15+v[1]) = 4\) viên kẹo. Vì \(2 > r[1]\), số kẹo trong hộp \(2\) không thay đổi. Số kẹo khi kết thúc mỗi ngày được tổng kết như sau:
| Ngày | Hộp 0 | Hộp 1 | Hộp 2 |
|---|---|---|---|
| 0 | 10 | 15 | 13 |
| 1 | 0 | 4 | 13 |
Do đó, hàm phải trả về [0, 4, 13].
IOI 2021, Ngày 1 — Distributing Candies (candies).
Kiến trúc sư Timothy đã thiết kế một trò chơi thoát hiểm mới. Trong trò chơi có \(n\) phòng, được đánh số từ \(0\) đến \(n-1\). Ban đầu, mỗi phòng có đúng một chìa khóa. Mỗi chìa khóa thuộc một loại, là một số nguyên từ \(0\) đến \(n-1\), bao gồm cả hai đầu mút. Chìa khóa trong phòng \(i\) (\(0 \le i \le n-1\)) thuộc loại \(r[i]\). Lưu ý rằng nhiều phòng có thể chứa chìa khóa cùng loại, tức là các giá trị \(r[i]\) không nhất thiết khác nhau.
Trò chơi còn có \(m\) đường kết nối hai chiều, được đánh số từ \(0\) đến \(m-1\). Đường kết nối \(j\) (\(0 \le j \le m-1\)) nối hai phòng khác nhau \(u[j]\) và \(v[j]\). Một cặp phòng có thể được nối bằng nhiều đường kết nối.
Trò chơi dành cho một người chơi, thu thập chìa khóa và di chuyển giữa các phòng qua các đường kết nối. Người chơi đi qua đường kết nối \(j\) khi sử dụng nó để di chuyển từ phòng \(u[j]\) đến phòng \(v[j]\) hoặc ngược lại. Người chơi chỉ có thể đi qua đường kết nối \(j\) nếu trước đó đã thu thập được một chìa khóa loại \(c[j]\).
Tại bất kỳ thời điểm nào trong trò chơi, người chơi đang ở một phòng \(x\) và có thể thực hiện hai loại hành động:
Người chơi bắt đầu trò chơi tại một phòng \(s\) mà không mang theo chìa khóa nào. Phòng \(t\) được gọi là có thể đến được từ phòng \(s\) nếu người chơi bắt đầu ở phòng \(s\) có thể thực hiện một dãy hành động như trên để đến phòng \(t\).
Với mỗi phòng \(i\) (\(0 \le i \le n-1\)), gọi \(p[i]\) là số phòng có thể đến được từ phòng \(i\). Timothy muốn biết tập hợp các chỉ số \(i\) đạt giá trị \(p[i]\) nhỏ nhất trong tất cả các chỉ số \(0 \le i \le n-1\).
Bạn cần cài đặt hàm sau:
std::vector<int> find_reachable(std::vector<int> r, std::vector<int> u,
std::vector<int> v, std::vector<int> c);
r: mảng độ dài \(n\). Với mỗi \(i\) (\(0 \le i \le n-1\)), chìa khóa trong phòng \(i\) thuộc loại \(r[i]\).u, v: hai mảng độ dài \(m\). Với mỗi \(j\) (\(0 \le j \le m-1\)), đường kết nối \(j\) nối hai phòng \(u[j]\) và \(v[j]\).c: mảng độ dài \(m\). Với mỗi \(j\) (\(0 \le j \le m-1\)), loại chìa khóa cần để đi qua đường kết nối \(j\) là \(c[j]\).Trình chấm mẫu đọc dữ liệu theo định dạng sau:
Trình chấm mẫu in giá trị trả về của find_reachable theo định dạng sau:
| Nhóm | Điểm | Ràng buộc bổ sung |
|---|---|---|
| 1 | 9 | \(c[j] = 0\) với mọi \(0 \le j \le m-1\) và \(n, m \le 200\). |
| 2 | 11 | \(n, m \le 200\). |
| 3 | 17 | \(n, m \le 2000\). |
| 4 | 30 | \(c[j] \le 29\) với mọi \(0 \le j \le m-1\) và \(r[i] \le 29\) với mọi \(0 \le i \le n-1\). |
| 5 | 33 | Không có ràng buộc bổ sung. |
Ví dụ 1
find_reachable([0, 1, 1, 2],
[0, 0, 1, 1, 3], [1, 2, 2, 3, 1], [0, 0, 1, 0, 2])
[0, 1, 1, 0]
Nếu bắt đầu trò chơi ở phòng \(0\), người chơi có thể thực hiện dãy hành động sau:
| Phòng hiện tại | Hành động |
|---|---|
| 0 | Thu thập chìa khóa loại \(0\). |
| 0 | Đi qua đường kết nối \(0\) đến phòng \(1\). |
| 1 | Thu thập chìa khóa loại \(1\). |
| 1 | Đi qua đường kết nối \(2\) đến phòng \(2\). |
| 2 | Đi qua đường kết nối \(2\) đến phòng \(1\). |
| 1 | Đi qua đường kết nối \(3\) đến phòng \(3\). |
Do đó, phòng \(3\) có thể đến được từ phòng \(0\). Tương tự, có thể xây dựng các dãy hành động cho thấy mọi phòng đều có thể đến được từ phòng \(0\), tức là \(p[0] = 4\). Bảng sau cho biết các phòng có thể đến được với từng phòng xuất phát:
| Phòng xuất phát \(i\) | Các phòng đến được | \(p[i]\) |
|---|---|---|
| 0 | [0, 1, 2, 3] | 4 |
| 1 | [1, 2] | 2 |
| 2 | [1, 2] | 2 |
| 3 | [1, 2, 3] | 3 |
Giá trị nhỏ nhất của \(p[i]\) trên tất cả các phòng là \(2\), đạt được với \(i = 1\) hoặc \(i = 2\). Vì vậy, hàm phải trả về [0, 1, 1, 0].
Ví dụ 2
find_reachable([0, 1, 1, 2, 2, 1, 2],
[0, 0, 1, 1, 2, 3, 3, 4, 4, 5],
[1, 2, 2, 3, 3, 4, 5, 5, 6, 6],
[0, 0, 1, 0, 0, 1, 2, 0, 2, 1])
[0, 1, 1, 0, 1, 0, 1]
Bảng sau cho biết các phòng có thể đến được:
| Phòng xuất phát \(i\) | Các phòng đến được | \(p[i]\) |
|---|---|---|
| 0 | [0, 1, 2, 3, 4, 5, 6] | 7 |
| 1 | [1, 2] | 2 |
| 2 | [1, 2] | 2 |
| 3 | [3, 4, 5, 6] | 4 |
| 4 | [4, 6] | 2 |
| 5 | [3, 4, 5, 6] | 4 |
| 6 | [4, 6] | 2 |
Giá trị nhỏ nhất của \(p[i]\) trên tất cả các phòng là \(2\), đạt được với \(i \in \{1, 2, 4, 6\}\). Vì vậy, hàm phải trả về [0, 1, 1, 0, 1, 0, 1].
Ví dụ 3
find_reachable([0, 0, 0], [0], [1], [0])
[0, 0, 1]
Bảng sau cho biết các phòng có thể đến được:
| Phòng xuất phát \(i\) | Các phòng đến được | \(p[i]\) |
|---|---|---|
| 0 | [0, 1] | 2 |
| 1 | [0, 1] | 2 |
| 2 | [2] | 1 |
Giá trị nhỏ nhất của \(p[i]\) trên tất cả các phòng là \(1\), đạt được khi \(i = 2\). Vì vậy, hàm phải trả về [0, 0, 1].
IOI 2021, Ngày 1 — Keys (keys).
Một công viên gần đó có \(n\) đài phun nước, được đánh số từ \(0\) đến \(n-1\). Ta mô hình hóa các đài phun nước bằng các điểm trên mặt phẳng tọa độ hai chiều. Cụ thể, đài phun nước \(i\) (\(0 \le i \le n-1\)) là điểm \((x[i], y[i])\), trong đó \(x[i]\) và \(y[i]\) là các số nguyên chẵn. Vị trí các đài phun nước đôi một khác nhau.
Kiến trúc sư Timothy được thuê để lên kế hoạch xây dựng một số con đường và bố trí một ghế đá cho mỗi con đường. Mỗi con đường là một đoạn thẳng nằm ngang hoặc thẳng đứng, có độ dài \(2\), với hai đầu mút là hai đài phun nước khác nhau. Các con đường phải được xây dựng sao cho có thể đi lại giữa hai đài phun nước bất kỳ bằng cách di chuyển dọc theo các con đường. Ban đầu, công viên không có con đường nào.
Với mỗi con đường, cần đặt đúng một ghế đá trong công viên và gán ghế đá đó cho con đường (nghĩa là ghế quay mặt về phía con đường). Mỗi ghế đá phải được đặt tại một điểm \((a, b)\) sao cho \(a\) và \(b\) là các số nguyên lẻ. Vị trí các ghế đá phải đôi một khác nhau. Một ghế đá tại \((a, b)\) chỉ có thể được gán cho một con đường nếu cả hai đầu mút của con đường đều thuộc tập hợp:
Ví dụ, ghế đá tại \((3,3)\) chỉ có thể được gán cho một con đường là một trong bốn đoạn thẳng \((2,2)\)–\((2,4)\), \((2,4)\)–\((4,4)\), \((4,4)\)–\((4,2)\), \((4,2)\)–\((2,2)\).
Hãy giúp Timothy xác định liệu có thể xây dựng các con đường, đặt và gán các ghế đá thỏa mãn tất cả các điều kiện trên hay không. Nếu có, hãy đưa ra một phương án hợp lệ. Nếu có nhiều phương án thỏa mãn tất cả các điều kiện, bạn có thể đưa ra bất kỳ phương án nào.
Bạn cần cài đặt hàm sau:
int construct_roads(std::vector<int> x, std::vector<int> y);
x, y: hai mảng độ dài \(n\). Với mỗi \(i\) (\(0 \le i \le n-1\)), đài phun nước \(i\) là điểm \((x[i], y[i])\), trong đó \(x[i]\) và \(y[i]\) là các số nguyên chẵn.build (xem dưới đây) đúng một lần để báo cáo phương án, sau đó trả về \(1\).build.Chương trình của bạn có thể gọi hàm sau để đưa ra một phương án xây dựng đường và bố trí ghế đá hợp lệ:
void build(std::vector<int> u, std::vector<int> v,
std::vector<int> a, std::vector<int> b);
u, v: hai mảng độ dài \(m\), biểu diễn các con đường cần xây dựng. Các con đường được đánh số từ \(0\) đến \(m-1\). Với mỗi \(j\) (\(0 \le j \le m-1\)), con đường \(j\) nối hai đài phun nước \(u[j]\) và \(v[j]\). Mỗi con đường phải là một đoạn thẳng nằm ngang hoặc thẳng đứng có độ dài \(2\). Hai con đường khác nhau bất kỳ có nhiều nhất một điểm chung (là một đài phun nước). Sau khi xây dựng, phải có thể đi lại giữa hai đài phun nước bất kỳ bằng cách di chuyển dọc theo các con đường.a, b: hai mảng độ dài \(m\), biểu diễn các ghế đá. Với mỗi \(j\) (\(0 \le j \le m-1\)), một ghế đá được đặt tại \((a[j], b[j])\) và được gán cho con đường \(j\). Không có hai ghế đá khác nhau nào cùng vị trí.Trình chấm mẫu đọc dữ liệu theo định dạng sau:
Trình chấm mẫu in kết quả theo định dạng sau:
construct_roads.Nếu construct_roads trả về \(1\) và build(u, v, a, b) được gọi, trình chấm mẫu in thêm:
| Nhóm | Điểm | Ràng buộc bổ sung |
|---|---|---|
| 1 | 5 | \(x[i] = 2\) với mọi \(0 \le i \le n-1\). |
| 2 | 10 | \(2 \le x[i] \le 4\) với mọi \(0 \le i \le n-1\). |
| 3 | 15 | \(2 \le x[i] \le 6\) với mọi \(0 \le i \le n-1\). |
| 4 | 20 | Có nhiều nhất một cách xây dựng các con đường sao cho có thể đi lại giữa hai đài phun nước bất kỳ bằng cách di chuyển dọc theo các con đường. |
| 5 | 20 | Không tồn tại bốn đài phun nước nằm tại bốn đỉnh của một hình vuông kích thước \(2 \times 2\). |
| 6 | 30 | Không có ràng buộc bổ sung. |
Ví dụ 1
construct_roads([4, 4, 6, 4, 2], [4, 6, 4, 2, 4])
1
Có \(5\) đài phun nước:
Có thể xây dựng \(4\) con đường sau, mỗi con đường nối hai đài phun nước, và đặt các ghế đá tương ứng:
| Nhãn con đường | Nhãn hai đài phun nước được nối | Vị trí ghế đá được gán |
|---|---|---|
| 0 | 0, 2 | \((5,5)\) |
| 1 | 0, 1 | \((3,5)\) |
| 2 | 3, 0 | \((5,3)\) |
| 3 | 4, 0 | \((3,3)\) |
Phương án này tương ứng với hình vẽ sau:
Để báo cáo phương án này, construct_roads phải thực hiện lời gọi sau:
build([0, 0, 3, 4], [2, 1, 0, 0], [5, 3, 5, 3], [5, 5, 3, 3])
Sau đó, construct_roads phải trả về \(1\).
Lưu ý rằng trong trường hợp này có nhiều phương án thỏa mãn yêu cầu, và tất cả đều được coi là đúng. Ví dụ, cũng có thể thực hiện lời gọi sau rồi trả về \(1\):
build([1, 2, 3, 4], [0, 0, 0, 0], [5, 5, 3, 3], [5, 3, 3, 5])
Ví dụ 2
construct_roads([2, 4], [2, 6])
0
Đài phun nước \(0\) ở \((2,2)\) và đài phun nước \(1\) ở \((4,6)\). Vì không có cách xây dựng các con đường thỏa mãn yêu cầu, construct_roads phải trả về \(0\) mà không gọi build.
IOI 2021, Ngày 1 — Fountain Parks (parks).