IOI 2026 — Day 2

Bộ đề bài

# Bài tập Điểm Thời gian: Giới hạn bộ nhớ
1 IOI 2026 Ngày 2 Bài 1 - Classroom Game 100 (p) 0.5s 1G
2 IOI 2026 Ngày 2 Bài 2 - Magic City 100 (p) 0.5s 2G
3 IOI 2026 Ngày 2 Bài 3 - Partition 100 (p) 1.0s 2G

1. IOI 2026 Ngày 2 Bài 1 - Classroom Game

Điểm: 100 (p) Thời gian: 0.5s Bộ nhớ: 1G Input: bàn phím Output: màn hình

Một trường trung học danh tiếng ở Tashkent tổ chức lễ kỷ niệm ngày thành lập bằng cách tổ chức một trò chơi giữa học sinh và giáo viên. Có \(N\) học sinh, được đánh số từ \(0\) đến \(N - 1\), đang ngồi trong lớp học. Mỗi học sinh cầm một tờ giấy có chứa một mảng các số nguyên. Ban đầu, mỗi tờ giấy đều trống, do đó tờ giấy chứa một mảng rỗng.

Các học sinh đang tham gia trò chơi với \(M\) giáo viên, được đánh số từ \(0\) đến \(M - 1\), và với hiệu trưởng. Trò chơi diễn ra trong \(M\) bước, cũng được đánh số từ \(0\) đến \(M - 1\). Trong bước \(j\), giáo viên \(j\) bước vào lớp học và diễn ra các sự kiện sau đây:

  1. Một số (có thể là không) học sinh giơ tay. Đảm bảo rằng trong mỗi bước, ít nhất có một học sinh không giơ tay, và mỗi học sinh chỉ được giơ tay tối đa một lần trong suốt trò chơi.
  2. Giáo viên xem các tờ giấy mà học sinh đang cầm, và có thể thay đổi nội dung trên các tờ giấy của những học sinh không giơ tay trong bước này. Đối với mỗi học sinh như vậy, giáo viên có thể thay thế nội dung trên tờ giấy của học sinh đó bằng một mảng số nguyên mới (có thể trống). Mỗi số nguyên phải nằm trong khoảng từ \(0\) đến \(63\) (tính cả hai đầu), và mảng mới này có thể có tối đa \(63\) phần tử.
  3. Sau khi thực hiện các điều chỉnh này, giáo viên \(j\) rời đi và các học sinh trao đổi các tờ giấy của mình theo một phép hoán vị bí mật \(P\). Cụ thể, mỗi học sinh \(i\) (\(0 \le i < N\)) sẽ trao tờ giấy của mình cho học sinh \(P[i]\), trong đó \(P[0], P[1], \ldots, P[N - 1]\) là \(N\) số nguyên phân biệt nằm trong khoảng từ \(0\) đến \(N - 1\) (tính cả hai đầu). Các giá trị của \(P\) là cố định trong suốt tất cả các bước của trò chơi, nhưng các giáo viên và hiệu trưởng không biết các giá trị này.

Khi tất cả \(M\) bước đã hoàn tất và lần trao đổi cuối cùng theo \(P\) được thực hiện, hiệu trưởng bước vào. Chỉ nhìn vào các tờ giấy mà các học sinh đang cầm, hiệu trưởng phải xác định, đối với mỗi học sinh \(i\) (\(0 \le i < N\)), bước \(j\) mà học sinh \(i\) đã giơ tay, hoặc kết luận rằng học sinh \(i\) chưa bao giờ giơ tay.

Giáo viên không được phép trao đổi với các giáo viên khác hoặc với hiệu trưởng, ngoại trừ việc thông qua các dãy số nguyên được viết trên các tờ giấy. Mỗi giáo viên đều biết tại bước nào họ bước vào lớp học.

Nhiệm vụ của bạn là thiết kế và cài đặt một chiến lược cho các giáo viên và hiệu trưởng để xác định chính xác liệu mỗi học sinh có giơ tay hay không và vào thời điểm nào. Điểm số của bạn sẽ phụ thuộc vào độ dài tối đa của bất kỳ dãy số nào được viết trên một tờ giấy: độ dài tối đa này càng ngắn thì điểm số của bạn có thể càng cao hoặc bằng.

Chi tiết cài đặt

Bạn cần cài đặt hai hàm, một dành cho các giáo viên và một dành cho hiệu trưởng.

Hàm bạn cần cài đặt cho các giáo viên là:

C++
std::vector<std::vector<int>> process_step(
    int N, int M, int R,
    std::vector<int> T,
    std::vector<std::vector<int>> A)
  • N: số lượng học sinh.
  • M: số lượng bước, và cũng là số lượng giáo viên.
  • R: số hiệu bước hiện tại (từ \(0\) đến \(M - 1\)).
  • T: một mảng (có thể rỗng) chứa các chỉ số của các học sinh giơ tay trong bước này, sắp xếp theo thứ tự tăng dần.
  • A: một mảng kích thước \(N\) mô tả các tờ giấy, trong đó \(A[i]\) (\(0 \le i < N\)) là mảng các số nguyên trên tờ giấy mà học sinh \(i\) đang cầm vào đầu bước này.
  • Hàm này được gọi đúng \(M\) lần cho mỗi trò chơi, theo thứ tự \(R = 0, 1, \ldots, M - 1\).

Hàm này cần trả về một mảng \(B\) kích thước \(N\), chứa các tờ giấy sau khi giáo viên chỉnh sửa, theo cùng định dạng như \(A\).

  • Đối với mỗi học sinh \(i\) đã giơ tay (tức là \(i\) xuất hiện trong \(T\)), tờ giấy không được thay đổi, do đó \(B[i] = A[i]\).
  • Đối với mỗi số nguyên \(i\) sao cho \(0 \le i < N\), kích thước của \(B[i]\) không được vượt quá \(63\), và mọi số nguyên trong \(B[i]\) phải nằm trong khoảng từ \(0\) đến \(63\), tính cả hai đầu.

Hàm bạn cần cài đặt cho hiệu trưởng là:

C++
std::vector<int> determine_steps(
    int N, int M, std::vector<std::vector<int>> A)
  • N, M: giống như trên.
  • A: một mảng kích thước \(N\), trong đó \(A[i]\) là mảng các số nguyên trên tờ giấy của học sinh \(i\) sau toàn bộ \(M\) bước.
  • Hàm này được gọi đúng một lần cho mỗi trò chơi, sau lời gọi cuối cùng đến hàm process_step.

Hàm này phải trả về một mảng \(D\) kích thước \(N\). Với mỗi \(i\) sao cho \(0 \le i < N\), mảng phải thỏa mãn điều kiện sau:

  • \(D[i] = j\) nếu học sinh \(i\) đã giơ tay trong bước \(j\); hoặc
  • \(D[i] = -1\) nếu học sinh \(i\) chưa bao giờ giơ tay trong suốt trò chơi.

Chương trình của bạn không được phép lưu trữ hoặc truyền bất kỳ thông tin nào từ một lời gọi hàm process_step sang lời gọi khác, trừ khi thông qua giá trị trả về của hàm process_step. Nếu chương trình của bạn cố gắng thực hiện điều này, điểm số của bạn trên CMS có thể không chính xác và có thể bị trừ sau khi cuộc thi kết thúc. Lưu ý rằng trình chấm có thể chạy nhiều tiến trình của chương trình của bạn cùng lúc. Điều này có nghĩa là các lời gọi đến process_step và determine_steps từ cùng một trò chơi có thể được chạy trong các tiến trình khác nhau, và các lời gọi đến process_step và determine_steps từ các trò chơi khác nhau có thể được chạy trong cùng một tiến trình. Mỗi trường hợp test bao gồm tối đa \(5\) trò chơi.

Các ràng buộc

  • \(2 \le N \le 63\).
  • \(1 \le M \le 63\).
  • Mỗi học sinh chỉ được giơ tay tối đa một lần trong suốt trò chơi. Nói cách khác, đối với mỗi học sinh \(i\), chỉ có tối đa một bước \(j\) mà tại đó \(i\) giơ tay.
  • Tại mỗi bước, ít nhất có một học sinh không giơ tay.

Các subtask và chấm điểm

Subtask Điểm Các ràng buộc thêm
1 4 \(M = 1\).
2 6 \(N = 2\).
3 9 \(P[i] = i\) với mọi \(0 \le i \le N - 1\).
4 25 Có tối đa một học sinh giơ tay tại mỗi bước.
5 56 Không có ràng buộc nào thêm.

Đối với mỗi trường hợp test, điểm số của bạn sẽ là \(0\) (được hiển thị dưới dạng Output isn't correct trong CMS) nếu giá trị trả về của bất kỳ lời gọi nào đến hàm process_step là không hợp lệ hoặc nếu giá trị trả về của bất kỳ lời gọi nào đến hàm determine_steps là không chính xác.

Trái lại, gọi \(C\) là kích thước lớn nhất của bất kỳ mảng nào trong bất kỳ \(B\) nào được trả về bởi process_step. Khi đó, điểm số cho một trường hợp test trong một subtask có điểm số \(S\) được tính theo công thức \(S \cdot X\), trong đó \(X\) phụ thuộc vào \(C\) theo bảng sau:

Điều kiện \(X\)
\(C \le 2\) \(1.00\)
\(C = 3\) \(0.75\)
\(C = 4\) \(0.55\)
\(5 \le C \le 13\) \(0.50 - 0.03 \cdot (C - 5)\)
\(14 \le C \le 63\) \(0.19 \cdot \frac{64 - C}{64 - 14} + 0.04\)

Ví dụ

Xét một kịch bản với \(N = 4\) học sinh, \(M = 2\) giáo viên và phép hoán vị \(P = [0, 3, 1, 2]\). Ban đầu, tất cả các tờ giấy đều trống.

Trình chấm trước tiên gọi:

C++
process_step(4, 2, 0, [1], [[], [], [], []])

Học sinh \(1\) đã giơ tay, do đó tờ giấy của em này không thể được chỉnh sửa. Giáo viên \(0\) có thể quyết định ghi \([10]\) vào tờ giấy của học sinh \(0\), ghi \([1, 63, 4]\) vào tờ giấy của học sinh \(3\), và để trống tờ giấy của học sinh \(2\). Để thực hiện điều này, hàm phải trả về \(B = [[10], [], [], [1, 63, 4]]\).

Sau khi giáo viên \(0\) ra khỏi phòng, các học sinh trao đổi tờ giấy của mình theo phép \(P\). Sau khi trao đổi, các tờ giấy sẽ là \(A = [[10], [], [1, 63, 4], []]\).

Trình chấm bây giờ gọi:

C++
process_step(4, 2, 1, [0, 3], [[10], [], [1, 63, 4], []])

Các học sinh \(0\) và \(3\) đã giơ tay, do đó tờ giấy của các em này không thể được sửa đổi. Giáo viên \(1\) có thể quyết định ghi \([0, 40]\) vào tờ giấy của học sinh \(1\) và ghi \([1, 50]\) vào tờ giấy của học sinh \(2\). Để thực hiện điều này, hàm phải trả về kết quả \(B = [[10], [0, 40], [1, 50], []]\).

Sau khi giáo viên \(1\) ra khỏi phòng, các tờ giấy lại được trao đổi theo quy tắc \(P\). Sau khi trao đổi, các tờ giấy sẽ là \(A = [[10], [1, 50], [], [0, 40]]\).

Cuối cùng, trình chấm gọi:

C++
determine_steps(4, 2, [[10], [1, 50], [], [0, 40]])

Hàm này phải trả về mảng \(D = [1, 0, -1, 1]\) vì các học sinh \(0\) và \(3\) đã giơ tay ở bước \(1\), học sinh \(1\) đã giơ tay ở bước \(0\), và học sinh \(2\) chưa bao giờ giơ tay. Trong ví dụ này, \(C = 3\).

Trình chấm mẫu

Định dạng dữ liệu vào:

N M
Q[0] Q[1] ... Q[N-1]
P[0] P[1] ... P[N-1]

Trong đó, \(Q\) là một mảng kích thước \(N\), với \(Q[i] = j\) nếu học sinh \(i\) giơ tay trong bước \(j\), hoặc \(Q[i] = -1\) nếu học sinh \(i\) không bao giờ giơ tay trong suốt trò chơi.

Định dạng kết quả ra:

Sau mỗi lời gọi hàm process_step, trình chấm mẫu sẽ in ra nội dung của các tờ giấy. Gọi \(K\) là kích thước của \(B\) và \(L[i]\) là kích thước của \(B[i]\) (với mỗi \(0 \le i < K\)). Trình chấm mẫu sẽ in ra \(B\) theo định dạng sau (kèm theo một dòng trống):

K
L[0] B[0][0] B[0][1] ... B[0][L[0]-1]
L[1] B[1][0] B[1][1] ... B[1][L[1]-1]
:
L[K-1] B[K-1][0] B[K-1][1] ... B[K-1][L[K-1]-1]

Trình chấm mẫu tiếp theo sẽ hoán vị các tờ giấy theo phép hoán vị \(P\). Nếu \(K \ne N\), trình chấm mẫu sẽ hiển thị thông báo lỗi và kết thúc ngay lập tức.

Sau khi gọi hàm determine_steps, trình chấm mẫu sẽ hiển thị kết quả:

C H
D[0] D[1] ... D[H-1]

Trong đó, \(H\) là kích thước của mảng \(D\) được trả về bởi determine_steps.


Nguồn: Đề bài chính thức IOI 2026, bản tiếng Việt (VNM), ngày 2 — Classroom Game (classroom).

2. IOI 2026 Ngày 2 Bài 2 - Magic City

Điểm: 100 (p) Thời gian: 0.5s Bộ nhớ: 2G Input: bàn phím Output: màn hình

Thị trưởng thủ đô Tashkent muốn thiết kế lại công viên giải trí nổi tiếng Magic City. Bạn được cho một số nguyên dương \(K\) và nhiệm vụ của bạn là thiết kế một công viên như sau:

  • Chọn một số nguyên \(N\), là số lượng điểm tham quan. Các điểm tham quan được đánh số từ \(0\) đến \(N - 1\).
  • Bổ sung các lối đi bộ hai chiều, mỗi lối đi bộ nằm giữa một cặp điểm tham quan phân biệt. Cho phép có nhiều hơn một lối đi bộ giữa cùng một cặp điểm tham quan. Không bắt buộc phải có khả năng di chuyển giữa mọi cặp điểm tham quan thông qua các lối đi bộ.
  • Đối với mỗi \(i\) sao cho \(0 \le i < N\), gán cho điểm tham quan \(i\) một loại \(T[i]\). Có \(2K\) loại điểm tham quan, được đánh số từ \(0\) đến \(2K - 1\). Mỗi loại cần được gán cho ít nhất một điểm tham quan. Các điểm tham quan khác nhau có thể cùng thuộc một loại.

Nghiên cứu thị trường cho thấy:

  1. Mỗi du khách thích tham quan ba điểm tham quan và không tham quan hai điểm liên tiếp có cùng loại.
  2. Du khách không thích những điểm tham quan có nhiều lối đi bộ.

Để làm hài lòng tất cả du khách tiềm năng, thị trưởng đã đặt ra hai điều kiện đối với thiết kế của bạn.

Ta gọi một bộ ba loại có thứ tự \((t_1, t_2, t_3)\) với \(0 \le t_1, t_2, t_3 < 2K\) là thú vị nếu \(t_1 \ne t_2\) và \(t_2 \ne t_3\). Lưu ý rằng \(t_1\) có thể bằng \(t_3\). Do đó, có \(2K \cdot (2K - 1)^2\) bộ ba thú vị.

Điều kiện 1: Với mỗi bộ ba thú vị \((t_1, t_2, t_3)\), phải tồn tại ba điểm tham quan \(a_1, a_2, a_3\) (với \(0 \le a_1, a_2, a_3 < N\)) sao cho:

  • Các loại của \(a_1, a_2, a_3\) tương ứng với \(t_1, t_2, t_3\). Tức là, \(T[a_1] = t_1\), \(T[a_2] = t_2\) và \(T[a_3] = t_3\).
  • Có một lối đi bộ giữa \(a_1\) và \(a_2\).
  • Có một lối đi bộ giữa \(a_2\) và \(a_3\).

Việc có hay không có lối đi bộ giữa \(a_1\) và \(a_3\) là không quan trọng. Cũng cần lưu ý rằng khi \(t_1 = t_3\), điểm tham quan \(a_1\) và \(a_3\) có thể giống nhau.

Điều kiện 2: Mỗi điểm tham quan chỉ có thể là điểm kết thúc của tối đa \(K\) lối đi bộ.

Bài toán này bao gồm \(50\) subtask chỉ yêu cầu kết quả ra với cách chấm điểm thành phần. Mỗi subtask tương ứng với một giá trị cụ thể của \(K\), và bạn phải thiết kế một công viên đáp ứng tất cả các điều kiện trên cho giá trị \(K\) đó. Điểm số của bạn phụ thuộc vào số lượng điểm tham quan trong lời giải của bạn: ít điểm tham quan hơn sẽ cho điểm số cao hơn hoặc bằng.

Chi tiết cài đặt

Có hai cách để nộp lời giải, và bạn có thể sử dụng một trong hai cách cho mỗi subtask:

  • Gọi hàm.
  • File kết quả ra.

Để gửi lời giải của bạn thông qua gọi hàm, bạn cần cài đặt hàm sau:

C++
std::pair<std::vector<int>,std::vector<std::pair<int, int>>> construct(int K)
  • \(K\): một nửa số loại điểm tham quan, và cũng là số lượng tối đa các lối đi bộ kết thúc ở cùng một điểm tham quan.
  • Hàm này được gọi đúng một lần cho mỗi subtask.

Hàm này cần trả về một cặp \((T, E)\) mô tả một công viên giải trí. Giả sử \(M\) là số lượng lối đi bộ trong công viên của bạn.

  • \(T\): một mảng có kích thước \(N\) mô tả loại của các điểm tham quan.
  • \(E\): một mảng có kích thước \(M\) mô tả các lối đi bộ. Với mỗi \(0 \le j < M\), \(E[j] = (U[j], V[j])\) biểu thị một lối đi bộ hai chiều giữa các điểm tham quan phân biệt \(U[j]\) và \(V[j]\).

Để gửi lời giải của bạn thông qua file kết quả ra, hãy tạo và gửi một file văn bản theo định dạng sau:

N M
T[0] T[1] ... T[N-1]
U[0] V[0]
U[1] V[1]
...
U[M-1] V[M-1]

Chú ý rằng lời giải của bạn phải đáp ứng các điều kiện sau để được coi là hợp lệ:

  • \(N \le 2000\).
  • \(0 \le T[i] < 2K\) với mỗi \(0 \le i < N\), và mỗi loại cần được gán cho ít nhất một điểm tham quan.
  • \(0 \le U[j], V[j] < N\) và \(U[j] \ne V[j]\) với mỗi \(0 \le j < M\).
  • Điều kiện 1 và 2 phải thỏa mãn.

Các ràng buộc

  • \(1 \le K \le 50\).

Chấm điểm

Có \(50\) subtask tương ứng với \(K\) từ \(1\) đến \(50\). Trong subtask thứ \(i\) (\(1 \le i \le 50\)), giá trị của \(K\) là \(i\).

Mỗi subtask có một điểm số \(S\) và một số lượng điểm tham quan mong muốn \(P\) theo bảng bên dưới.

Subtask \(S\) \(P\)
1 1 2
2 8 12
3 9 24
4 9 40
5 9 50
6–10 4 \(12 \cdot K\)
11–12 3 \(12 \cdot K\)
13–50 1 \(12 \cdot K\)

Đối với mỗi subtask, nếu lời giải của bạn không mô tả một công viên giải trí hợp lệ, thì điểm số của lời giải sẽ là \(0\) (được phản hồi là Output isn't correct trong CMS).

Ngược lại, điểm số của bạn được tính dựa trên \(N\) và các tham số \(S\) và \(P\) như sau:

Điều kiện Điểm
\(N \le P\) \(S\)
\(P < N \le 2P\) \(\left(0.4 + 0.3 \cdot \frac{2P - N}{P}\right) \cdot S\)
\(2P < N \le 2000\) \(\left(0.1 + 0.3 \cdot \frac{2P}{N}\right) \cdot S\)

Ví dụ

Xét lời gọi hàm sau:

C++
construct(1)

Trong ví dụ này, \(K = 1\), vậy có \(2K = 2\) loại điểm tham quan. Hình dưới đây mô tả một giải pháp hợp lệ với \(N = 4\) điểm tham quan và \(M = 2\) lối đi bộ. Các điểm tham quan \(0, 1, 2\) thuộc loại \(0\), và điểm tham quan \(3\) thuộc loại \(1\).

Có hai bộ ba thú vị:

  • Đối với bộ ba loại \((0, 1, 0)\), có thể chọn \((a_1, a_2, a_3) = (2, 3, 2)\).
  • Đối với bộ ba loại \((1, 0, 1)\), có thể chọn \((a_1, a_2, a_3) = (3, 2, 3)\).

Điều này có nghĩa là Điều kiện 1 được thỏa mãn.

Hàm có thể trả về cặp \(([0, 0, 0, 1], [(0, 1), (2, 3)])\). Chú ý rằng lời giải được cung cấp cho ví dụ này có thể không tối ưu với \(K = 1\).

Trình chấm mẫu

Định dạng dữ liệu vào:

K

Định dạng kết quả ra:

N M
T[0] T[1] ... T[N-1]
U[0] V[0]
U[1] V[1]
...
U[M-1] V[M-1]

Chú ý rằng kết quả của trình chấm mẫu phù hợp với định dạng yêu cầu của file đầu ra.

Nguồn: Đề thi chính thức IOI 2026, ngày thi thứ hai, bản tiếng Việt (VNM).

3. IOI 2026 Ngày 2 Bài 3 - Partition

Điểm: 100 (p) Thời gian: 1.0s Bộ nhớ: 2G Input: bàn phím Output: màn hình

Temur và trợ lý của anh, Ulug'bek, đang chuẩn bị một trò ảo thuật cho chương trình Uzbekistan Got Talent. Trò ảo thuật này xoay quanh việc Temur giải quyết một bài toán phân hoạch sau đây: phân chia một bộ các số nguyên dương đã cho thành \(K\) nhóm không rỗng sao cho tổng các phần tử trong mỗi nhóm đều bằng nhau. Nói cách khác, mỗi số nguyên trong bộ phải được gán vào đúng một trong \(K\) nhóm, và tổng các phần tử trong mỗi nhóm phải bằng nhau. Ví dụ, nếu bộ đã cho là \([2, 1, 6, 4, 5]\) và \(K = 3\), một cách phân chia hợp lệ sẽ là \([2, 4]\), \([1, 5]\) và \([6]\). Trong trường hợp này, tổng các phần tử trong mỗi nhóm chính xác là \(6\).

Trò ảo thuật được thực hiện như sau:

  1. Ulug'bek và Temur vào các phòng riêng biệt và không thể giao tiếp với nhau.
  2. Một thành viên ban giám khảo đưa cho Ulug'bek một mảng \(A\) gồm \(N\) số nguyên dương, \(A[0], A[1], \ldots, A[N - 1]\), trong đó mỗi giá trị nằm trong khoảng từ \(1\) đến \(M\) (tính cả hai đầu). Thành viên ban giám khảo cũng đưa cho Ulug'bek giá trị \(K\).
  3. Ulug'bek chọn tối đa \(K - 1\) số nguyên (không nhất thiết phải khác nhau) để thêm như các phần tử mới vào mảng \(A\). Mỗi số nguyên được thêm vào cũng phải nằm trong khoảng từ \(1\) đến \(M\) (tính cả hai đầu).
  4. Ban giám khảo thêm các số nguyên do Ulug'bek chọn vào mảng ban đầu. Mảng mở rộng này sau đó được sắp xếp theo thứ tự không giảm và được chuyển cho Temur, kèm theo giá trị của \(K\).
  5. Temur phải giải quyết bài toán phân hoạch cho mảng mở rộng và đã được sắp xếp này.

Nhiệm vụ của bạn là thiết kế và cài đặt một chiến lược cho Temur và Ulug'bek. Có thể chứng minh rằng, với các điều kiện ràng buộc đã cho, luôn tồn tại một chiến lược cho phép họ giải quyết thành công bài toán phân hoạch, bất kể mảng \(A\) nào do ban giám khảo cung cấp.

Chi tiết cài đặt

Bạn cần thực hiện hai hàm.

Hàm mà bạn cần cài đặt cho Ulug'bek là:

C++
std::vector<int> add_numbers(std::vector<int> A, int K, int M)
  • \(A\): một mảng có kích thước \(N\), biểu diễn mảng ban đầu được cung cấp cho Ulug'bek.
  • \(K\): số nhóm mong muốn; lưu ý rằng Ulug'bek có thể thêm tối đa \(K - 1\) số nguyên vào mảng.
  • \(M\): giá trị lớn nhất cho phép đối với mỗi số nguyên ban đầu và số nguyên mới được thêm vào.
  • Hàm này được gọi đúng một lần cho mỗi trường hợp test.

Hàm này cần trả về một mảng \(C\) chứa các số nguyên mà Ulug'bek muốn thêm vào mảng ban đầu. Gọi \(S\) là kích thước của mảng \(C\).

  • \(S\) phải nhỏ hơn hoặc bằng \(K - 1\).
  • Mỗi phần tử của \(C\) phải nằm trong khoảng từ \(1\) đến \(M\) (tính cả hai đầu).

Hàm mà bạn cần cài đặt cho Temur là:

C++
std::vector<int> find_partition(std::vector<int> B, int K)
  • \(B\): một mảng có kích thước \(N + S\) chứa cả các số nguyên ban đầu từ \(A\) và các số nguyên mà Ulug'bek đã thêm vào. Các phần tử của mảng \(B\) được sắp xếp theo thứ tự không giảm.
  • \(K\): số lượng nhóm mục tiêu.
  • Hàm này được gọi đúng một lần cho mỗi trường hợp test.

Hàm này cần trả về một mảng \(P\) biểu thị sự phân hoạch của \(B\) thành \(K\) nhóm không giao nhau.

  • Kích thước của \(P\) phải bằng \(N + S\).
  • Với mỗi \(j\) sao cho \(0 \le j < N + S\), \(P[j]\) biểu thị nhóm mà \(B[j]\) thuộc về.
  • Các nhóm cần được đánh số từ \(0\) đến \(K - 1\), nghĩa là \(0 \le P[j] < K\) phải đúng với mọi \(0 \le j < N + S\).
  • Với mỗi \(i\) nằm giữa \(0\) và \(K - 1\) (tính cả hai đầu), phải có ít nhất một phần tử \(j\) (\(0 \le j < N + S\)) sao cho \(P[j] = i\).
  • Tổng các phần tử được gán cho mỗi nhóm trong số \(K\) nhóm phải giống nhau.

Trong quá trình chấm thực tế, một chương trình gọi các hàm nêu trên sẽ được chạy đúng hai lần.

  1. Trong lần chạy đầu tiên của chương trình, add_numbers được gọi một lần duy nhất. Mảng trả về được hệ thống chấm xử lý để tính ra mảng \(B\).
  2. Trong lần chạy thứ hai của chương trình, find_partition được gọi một lần duy nhất.

Các ràng buộc

  • \(3 \le N \le 100\,000\).
  • \(2 \le K \le 100\,000\).
  • \(K \le N\).
  • \(1 \le M \le 10^9\).
  • \(1 \le A[i] \le M\) với mỗi \(i\) sao cho \(0 \le i < N\).

Các subtask

Subtask Điểm Các ràng buộc thêm
1 5 \(N = 3\)
2 4 \(M = 1\)
3 7 \(M \le 2\)
4 10 \(N \le 10\)
5 7 \(K = 2\)
6 12 \(K \le 3\)
7 17 \(K \le 10\)
8 20 \(K \le 100\)
9 18 Không có ràng buộc nào thêm.

Ví dụ

Xét lời gọi hàm sau:

C++
add_numbers([8, 2, 9, 6, 1, 5, 5], 3, 9)

Trong ví dụ này \(A = [8, 2, 9, 6, 1, 5, 5]\). Ta muốn phân hoạch các số thành \(K = 3\) nhóm. Ulug'bek có thể thêm các số từ \(1\) đến \(M = 9\).

Hàm có thể trả về \([5, 4]\), có nghĩa là Ulug'bek quyết định thêm \(S = 2\) số nguyên mới: \(5\) và \(4\). Điều này hợp lệ vì cả hai phần tử đều nằm giữa \(1\) và \(M = 9\).

Mảng mở rộng sau đó được sắp xếp và truyền cho Temur qua lời gọi sau:

C++
find_partition([1, 2, 4, 5, 5, 5, 6, 8, 9], 3)

Ta có thể chia các số nguyên từ mảng này thành ba nhóm sau: \([1, 5, 9]\), \([2, 5, 8]\) và \([4, 5, 6]\). Lưu ý rằng tổng của mỗi nhóm này bằng \(15\). Để chỉ ra phân hoạch này, hàm cần trả về mảng \([0, 1, 2, 0, 1, 2, 2, 1, 0]\).

Trình chấm mẫu

Định dạng dữ liệu vào:

N K M
A[0] A[1] ... A[N-1]

Định dạng kết quả ra:

Sau khi lời gọi hàm add_numbers hoàn tất, trình chấm mẫu sẽ:

  • Tính ra mảng đã được sắp xếp \(B\).
  • In ra các mảng \(C\) và \(B\) theo định dạng sau (kết thúc bởi một dòng trống):
S
C[0] C[1] ... C[S-1]
B[0] B[1] ... B[N+S-1]

Sau khi lời gọi find_partition hoàn tất, trình chấm sẽ đưa ra:

L
P[0] P[1] ... P[L-1]

Trong đó, \(L\) là kích thước của mảng \(P\) được trả về bởi find_partition.

Nguồn: Đề thi chính thức IOI 2026, ngày thi thứ hai, bản tiếng Việt (VNM).