Đề thi bài 3 Olympic 30/4 môn tin học
Bài 3: Đoạn đường đẹp nhất (Đề thi Tin học 10 – Olympic 30/4/2013)
Trong thời gian vừa qua, người dân ở hành tinh Alpha đã vui mừng chào đó sự xuất hiện của con đường mới XYZ. Được đầu tư rất nhiều nguồn vốn, con đường này được coi là con đường đẹp nhất hành tinh. Những tòa nhà chỉ ở một bên đường với độ cao khác nhau. Theo các giáo sư, đoạn đường đẹp nhất là đoạn đường ở đó độ cao trung bình của các tòa nhà bằng K. Cụ thể, có N tòa nhà nằm cạnh nhau ở một bên của con đường. Tòa nhà thứ i tính từ đầu đường có độ cao là Ai.
Yêu cầu: Hãy tìm đoạn đường dài nhất chứa các tòa nhà liên tiếp sao cho chúng có độ cao trung bình là K.
Dữ liệu vào: cho trong ROAD.INP:
– Dòng 1: ghi hai số nguyên N và K (1≤ N ≤ 105; 0 ≤ K ≤ 109).
– N dòng tiếp theo, dòng thứ i ghi số nguyên Ai (0 ≤ Ai ≤ 109).
Kết quả ra: ghi vào ROAD.OUT:
Nếu không tìm được đoạn nào có các tòa nhà có độ cao trung bình là K thì ghi ra một số 0 duy nhất. Ngược lại, ghi ra hai số u, v với ý nghĩa: u là vị trí bắt đầu của đoạn đường và v là độ dài đoạn đường. Nếu có nhiều đáp án thì ghi ra đáp án có u nhỏ nhất.
Ví dụ:
ROAD.INP | ROAD.OUT |
4 5 2 4 5 6 | 2 3 |
ĐÁP ÁN – HƯỚNG DẪN GIẢI
Cách 1: O(n^3)
Vector nghiệm: (i, j)
Procedure isOK(i, j: integer); //O(N) Var p, q: integer; S:longint; Begin S:=0; For p:=i to j do S:= S + a[p]; If S div (i-j+1) = K then If j-i+1 >v then Begin u:=i; v:= j-i+1; End; End; Procedure Solve; //O(N^2) Var i, j: integer; Begin Max:=0; For i:=1 to N-1 do For j:=i+1 to N do isOK(i,j); End;
Nhận xét: với độ phức tạp O(N^3) thì chỉ phủ hợp với N<10^3.
Cách 2: O(N^2)
Procedure isOK(i, j: integer); //O(1) Begin If (S[j] – S[i-1]) div (i-j+1) = K then If j-i+1 >v then Begin u:=i; v:= j-i+1; End; End; Procedure Solve; //O(N^2) Var i, j: integer; Begin Max:=0; For i:=1 to N-1 do For j:=i+1 to N do isOK(i,j); End;
Nhận xét: với độ phức tạp O(N^2) thì chỉ phủ hợp với N<30 000, nhưng vẫn chưa đạt đến N = 10^5 của đề bài.
Cách 3: O(NlogN)
Procedure isOK(j: integer); //O(logN) Var i0: integer; Begin i0:=BinarySearch(S[j] – K(j+1)) then //O(logN) if i0>0 then If j-i0+1 >v then Begin u:=i0; v:= j-i0+1; End; End; Procedure Solve; //O(N) Var j: integer; Begin Max:=0; For j:=1 to N do isOK(j); End; Begin //main program T[i].value = S[i-1] + K.i; T[i].i = i; //với mọi i, O(N) QuickSort(T) //O(NlogN) Solve; // O(NlogN) End.
Nhận xét: độ phức tạp O(NlogN), chạy tốt với N = 10^7.
Chào bạn,
Trước xin cám ơn bạn vì lời giải. Bạn có thể xem lại giúp mình ở cách 3. Mình thấy trong chương trình chính có khởi tạo mãng T rồi sort lại, nhưng không thấy dùng ở đâu cả, còn trong thủ tục IsOK thì có dùng hàm K nhưng không thấy định nghĩa.
Mình đang tự học nên không hiểu lắm, nghĩ mãi không ra. Mong bạn giúp. Xin chân thành cám ơn.