Algorithmic Crush challenge on Hackerrank
Xin chào ae,
Vào thẳng vấn đề luôn nhé, đây là 1 challenge nằm trong subdomain Arrays của Data structures & Algorithms trên Hackerrank (hard): https://www.hackerrank.com/challenges/crush
Đây là code giải của e:
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int n, m, a, b, k;
std::cin >> n >> m;
std::vector<int> arr(n, 0);
for (int i = 0; i < m; ++i) {
std::cin >> a >> b >> k;
for (int j = a - 1; j < b; ++j)
arr[j] += k;
}
auto it = std::max_element(arr.begin(), arr.end());
std::cout << *it;
return 0;
}
Code đó bị sai ở testcase 4, 5, 6, còn từ testcase 7 đến 13 là bị Terminated due to timeout!
Có ai bt vi sao sai ko ạ? Còn timeout thì chắc để tính sau, vì đây là hard ^^
Và ai có solution thì hướng dẫn cho e luôn nhé
E cảm ơn trc
P/S: Đây là I/O của testcase 4:
INPUT: http://codepad.org/1r3UWWfx
OUTPUT: 7542539201
.
Chắc bạn bị tràn rồi.
Thay = long long thử xem.
Code thử cũng bị timeout vụ này có vẻ khó @_@!
O(n*m) với m, n to thì bảo sao chả TLE.
Bài này dùng Interval Tree nhé.
Hình như đây là kiểu số nguyên lớn nhất rồi hả a?
Nó nằm trong subdomain Arrays mà dùng Tree có hơi “lạ” ko a?
Lạ gì, cài Interval Tree dùng mảng mà. Mà cài Interval Tree là dùng Data Structure rồi còn gì, quá chuẩn rồi
Kiểu số nguyên có dấu lớn nhất là long long, còn không dấu lớn nhất là unsigned long long.
Bài này không cần dùng interval tree , chỉ cần dùng mảng và tính chất liên tiếp của việc thêm vào đoạn [L,R]:
Theo mọi người thì phần nào chạy thối thời gian nhất ?
Theo mình phần nhập dữ liệu @_@!
@Phong_Ky_Vo: Nếu dùng Interval Tree thì vừa nhập vừa xử lí là được.
@Gio:
Bạn thử code xem.
À mà bài này cũng có cách dùng Binary Index Tree nữa @@
Bạn thử submit chưa @@
Mình vừa submit xong, accept rôi bạn
Hi Gió.
Làm sao lại nghĩ được cách hay vậy ???
xem mảng n+2 phần tử đó là mảng chênh lệch với quy luật:
diff[i] = arr[i] - arr[i-1]
cái này rất tiện ích, muốn cộng k cho b-a+1 phần tử từ a tới b, thay vì cộng b-a+1 lần, ở đây ta chỉ làm 2 phép toán ở đầu và cuối:
diff[a] += k
vàdiff[b+1] -= k
, nghĩa là update độ chênh lệch ở đầu và cuối, còn mấy phần tử ở giữa ko cần update độ chênh lệch:arr[a] += k
thì đương nhiênarr[a] - arr[a-1]
tăng thêm k đơn vị, vì arr[a-1] ko đổi mà arr[a] tăng thêm k. Vậy ta updatediff[a] += k
.arr[b] += k
thìarr[b+1] - arr[b]
giảm đi k đơn vị, vì arr[b] tăng thêm k mà arr[b+1] ko tăng. Vậy ta cần updatediff[b+1] -= k
diff[a+i] = arr[a+i] - arr[a+i-1]
với 0 < i ≤ b-a ko tăng giảm vì arr[a+i] và arr[a+i-1] đều tăng thêm k đơn vị.thay vì update mn lần, ta chỉ cần update m2 lần, hay giảm từ O(mn) xuống còn O(m)
để chuyển mảng
diff
thành mảngarr
ban đầu, ta chỉ cần cộngdiff[i] += diff[i-1]
với 1 ≤ i ≤ n là chuyển diff thành arr:diff
có index từ 0 tới n+1,arr
có index từ 1 tới ndiff[1] = diff[1] + diff[0]
.diff[2] = diff[2] + diff[1]
.vậy là thu được arr sau cùng với O(n) phép cộng, chỉ cần tìm max element (O(n)) nữa là xong. Tổng quát bài toán có đpt O(n+m).
(khi áp dụng thuật toán này
diff
chỉ cầnn+1
phần tử cũng được, bỏ phần tử diff[0])