Solutions of Inversions query 3 - MarisaOJ: Marisa Online Judge

Solutions of Inversions query 3

Select solution language

Write solution here.


User Avatar lenhanbo    Created at    5 likes

**Ta sẽ chia bài toán ra từng subtask.** Để thuận tiện hơn, ta sẽ gọi B(i) là chỉ số block của vị trí i 1. Giả sử Q = 1 : + Ta có thể duyệt từ l đến r rồi đếm số lượng phần tử >Ai bằng cấu trúc dữ liệu như Fenwick tree hoặc Segment tree. 2. Giả sử N1000 : + Gọi f(i,j) là số lượng phần tử Ax>Aj trong đoạn [ij]. + Gọi dp(i,j) là số nghịch đảo trong đoạn [ij]. + Ta có dp(l,r) = i=lr f(l,i). + Ta có thể chuẩn bị 2 mảng trong O(n2) và truy vấn trong O(1). 3. Từ (1)(2), ta có thể chia căn như sau : + Đầu tiên ta sẽ chia mảng thành n block. + Với mỗi block ta sẽ sort lại. + Gọi g(i,j) là số lượng phần tử Ax > Ai (B(x) = j). + Ta có thể tính g(i,j) bằng hàm [lower_bound](https://en.cppreference.com/w/cpp/algorithm/lower_bound) trong c++. + Từ đó, ta có thể tính 2 mảng ở như (2) nhưng thay vì dùng chỉ số phần tử thì ta tính với **chỉ số block**. Độ phức tạp cho bước này là O(n × n × log(n)). + Khi truy vấn, ta dễ dàng tính được số nghịch đảo trong đoạn block [B(l)+1B(r)1]. + Gọi pref(i,j) = k=1j g(i,k).Ta có thể tính nhanh nghịch đảo của 2 phần dư với phần block (P/S: đối với phần dư bên trái thì phải xử lí ngược với phần dư bên phải). + Đối với nghịch đảo giữa 2 phần dư thì ta có thể duyệt qua từng phần tử rồi dùng cấu trúc dữ liệu như Fenwick/Segment tree. + Tổng độ phức tạp là O( (n+q) × n × log(n)). 4. Tới đây vẫn chưa kết thúc, với độ phức tạp của (3) thì ta có thể bị **TLE** với bộ test đủ mạnh. + Tới đây ta vẫn có thể tối ưu được nữa, phần còn lại xin mời bạn đọc thử sức.