Skip to content

DTQG #1 Editorial

15 Nov 2023

Bài 1

Thêm hai thành phố "ảo" tại khoảng cách 00dd. Ta cần di chuyển từ thành phố thứ 00 đến thành phố thứ m+1m + 1.

Xét quãng đường di chuyển giữa hai thành phố LLRR. Ta đang có bình xăng đang chứa XX lít. Ta xây dựng hàm tính đáp án: F(L,R,X)F(L, R, X).

Giả sử thành phố xăng rẻ nhất giữa hai thành phố LLRR là thành phố ii. Ta biết chắc rằng nên ưu tiên mua xăng ở thành phố ii nhất. Do đó ta gọi đến F(L,i,X)F(L, i, X). Hàm FF sẽ trả về số tiền nhỏ nhất và số xăng còn lại (có thể phải mua thêm vừa đủ để đến được RR). Sau đó mới lấy số lượng xăng còn lại, giả sử là YY, để gọi tiếp hàm F(i,R,Y)F(i, R, Y).

Ta thấy cách làm trên giống mô hình chia để trị, mỗi lần ta chia L,RL, R ra thành L,iL, ii,Ri, R. Thực tế ta không duyệt từ LL đến ii hay từ ii đến RR như chia để trị. Mỗi giá trị ii, ta chỉ xét duy nhất một lần. Hàm FF sẽ chỉ mất O(n)O(n).

Vậy ĐPT là O(n×log)O(n \times log) do ta cần sort và chuẩn bị mảng thưa để tìm min.

Bài 2

Nhận thấy là ta luôn phải ưu tiên những thành phố có giá xăng là c=1c = 1. Do đó ta đi tìm cách xây dựng hai mảng:

  • nxt(i, j): trạm xăng thứ 2j2^j sau ii có giá xăng bằng 11.
  • cost(i, j): chi phí để di chuyển đến trạm xăng trên.

Gấp đôi mảng và ta cứ nhảy theo sparse table.

Bài 3

Xét x=min1i<jkvivjx = min_{1 \le i < j \le k} |v_i - v_j|, ta thấy rằng để tính đáp án chính xác bằng xx sẽ rất khó. Do đó ta nghĩ tới việc tính đáp án cho các dãy có độ chênh vênh x\ge x.

Sắp xếp lại dãy, lúc này độ chênh vênh của dãy luôn là min của hiệu giữa hai phần tử liên tiếp được chọn. Ta gọi dp(i,j)dp(i, j) là số dãy có độ chênh vệnh x\ge x nếu xét đến ii, đã chọn jj phần tử. Nếu chọn ii, phần tử liền trước ii phải là jj với aiajxa_i - a_j \ge x. Do đó ta có thể dùng hai con trỏ và tổng tiền tố để tối ưu.

Tổng tìm được sẽ là dp(n,k)×xdp(n, k) \times x. Ta trừ đi tổng khi tính cho x+1x + 1 sẽ ra tổng khi độ chênh vênh đúng bằng xx.