# Dãy Liên Tiếp - Solution
## Subtask 3
Do $1 \le l \le r \le 5000$, và $a_i \le 5000$, ta có thể dùng thuật toán $O(n \times q)$ bằng đếm phân phối như sau:
- Gọi $cnt_i$ là số lần xuất hiện của giá trị $i$ trong dãy $C$ được tạo bởi đoạn $[l,r]$.
- Ta sẽ duyệt qua từng $a_i$ trong $[l,r]$, ta biết rằng giá trị $a_i$ này sẽ xuất hiện trong $(i-l+1)\times(r-i+1)$ đoạn con của đoạn $[l,r]$. Vậy nên, ta cộng thêm cho $cnt_{a_i}$ một lượng bằng $(i-l+1)\times(r-i+1)$.
- Sau đó, ta duyệt các giá trị $i$ trong khoảng từ $[1,5000]$, nếu tổng tiền tố của nó không bé hơn $k$ thì $i$ chính là đáp án của truy vấn.
## Subtask 4
Dựa vào nhận xét, giá trị $a_i$ này sẽ xuất hiện trong $(i-l+1)\times(r-i+1)$ đoạn con của đoạn $[l,r]$, ta có thể biến đổi một chút như sau:
- $(i-l+1)\times(r-i+1) = -i^2 + i\times(r+l) + (r-l+1 - r\times l)$
Từ đây, với mảng $cnt_i$ được định nghĩa như subtask $3$, ta có thể tính $cnt_x = \sum (-i^2 + i\times(r+l) + (r-l+1 - r\times l))$, $\forall i \in [l,r]$ và $a_i = x$.
Do $1 \le a_i \le 100$, ta có thể dùng mảng cộng dồn để tính tương ứng với $3$ giá trị trong phép tính.
## Subtask 5
Xét với mỗi truy vấn, nếu ta hoàn toàn có thể tìm kiếm nhị phân kết quả của nó, tức là chỉ cần kiểm tra xem liệu giá trị $x$ **lớn hơn hoặc bằng** bao nhiêu giá trị của dãy $C$ tạo bởi đoạn $[l,r]$. Tuy nhiên, việc kiểm tra này sẽ mất $O(n)$.
Vậy nên, ta cần áp dụng phương pháp chặt nhị phân song song để xử lí cùng lúc tất cả các truy vấn. Kết hợp thêm với phương pháp sweepline $1$ chiều để check.
Độ phức tạp: $O(n \times log^2)$.
## Subtask 6
Thay vì cần chặt nhị phân song song, ta có thể thay bằng Persistent Tree để cho ra độ phức tạp $O(n\times log)$.
## Code mẫu (subtask $3,4,5$):
```cpp=
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e5+5;
int n,q;
int a[N];
int mx = 0;
namespace sub3 {
const int N = 5050;
int cnt[N];
void solve () {
while (q--) {
int l,r,k; cin >> l >> r >> k;
int cur = 0;
for (int i=1; i<=5000; i++) cnt[i] = 0;
for (int i=l; i<=r; i++) {
cnt[a[i]] += (i-l+1)*(r-i+1);
}
for (int i=1; i<=5000; i++) {
cur += cnt[i];
if (cur >= k) {
cout << i << '\n';
break;
}
}
}
}
}
namespace sub4 {
int f[101][N],s[101][N],cnt[101][N];
int get (int i, int l, int r) {
return (f[i][r]-f[i][l-1])*(r+l) + (s[i][r]-s[i][l-1]) + (cnt[i][r]-cnt[i][l-1])*(r-l+1-r*l);
}
void solve () {
for (int i=1; i<=n; i++) {
for (int j=1; j<=100; j++) f[j][i] = f[j][i-1],s[j][i] = s[j][i-1],cnt[j][i] = cnt[j][i-1];
f[a[i]][i] += i;
s[a[i]][i] += -(i*i);
cnt[a[i]][i] ++;
}
while (q--) {
int l,r,k; cin >> l >> r >> k;
int res = 0;
for (int i=1; i<=100; i++) {
res += get(i,l,r);
if (res >=k) {
cout << i << '\n';
break;
}
}
}
}
}
namespace sub5 {
struct fenwick {
int n;
vector<int> bit;
fenwick (int n) : n(n), bit(n+6){}
void update (int u, int val) {
while (u <= n) bit[u] += val, u += u&(-u);
}
int get (int u) {
int ans = 0;
while (u>0) ans += bit[u], u -= u&(-u);
return ans;
}
void xoa () {
for (int i=1; i<=n; i++) bit[i] = 0;
}
};
struct qr {
int l,r,k;
}go[N];
struct vcl {
int sig,mid,id;
}; vector<vcl> event[N];
int l[N],r[N],res[N],val[N];
void solve () {
for (int i=1; i<=q; i++) {
cin >> go[i].l >> go[i].r >> go[i].k;
l[i] = 1; r[i] = mx;
}
bool gone = false;
fenwick f(mx),s(mx),cnt(mx);
while (gone == false) {
gone = true;
f.xoa(); s.xoa(); cnt.xoa();
for (int i=1; i<=q; i++) {
val[i] = 0;
if (l[i] > r[i]) continue;
gone = false;
int mid = (r[i] + l[i]) >> 1;
event[go[i].l].push_back({1,mid,i});
event[go[i].r+1].push_back({-1,mid,i});
}
for (int i=n; i>=1; i--) {
f.update (a[i],i);
s.update (a[i],-(i*i));
cnt.update (a[i],1);
for (int cc=0; cc<event[i].size(); cc++) {
vcl cur = event[i][cc];
int id = cur.id;
int add = f.get(cur.mid)*(go[id].l+go[id].r)+s.get(cur.mid)+cnt.get(cur.mid)*(go[id].r-go[id].l+1-go[id].r*go[id].l);
add = cur.sig*add;
val[id] += add;
}
event[i].clear();
}
event[n+1].clear();
for (int i=1; i<=q; i++) {
if (l[i] > r[i]) continue;
int mid = (r[i] + l[i]) >> 1;
if (val[i] >= go[i].k) res[i] = mid, r[i] = mid - 1;
else l[i] = mid + 1;
}
}
for (int i=1; i<=q; i++) cout << res[i] << '\n';
}
}
signed main () {
ios_base::sync_with_stdio(false);
cin.tie(0);
freopen("DLT.inp","r", stdin);
freopen("DLT.out", "w", stdout);
cin >> n >> q;
for (int i=1; i<=n; i++) cin >> a[i], mx = max (mx,a[i]);
if (mx <= 5000&&n<=5000&&q<=5000) sub3::solve();
else if (mx<=100) sub4::solve();
else sub5::solve();
}
```