You are a given a list of integers $a_1, a_2, \ldots, a_n$ and $s$ of its segments $[l_j; r_j]$ (where $1 \le l_j \le r_j \le n$).
You need to select exactly $m$ segments in such a way that the $k$-th order statistic of the multiset of $a_i$, where $i$ is contained in at least one segment, is the smallest possible. If it’s impossible to select a set of $m$ segments in such a way that the multiset contains at least $k$ elements, print -1.
The $k$-th order statistic of a multiset is the value of the $k$-th element after sorting the multiset in non-descending order.
Input
The first line contains four integers $n$, $s$, $m$ and $k$ ($1 \le m \le s \le 1500$, $1 \le k \le n \le 1500$) — the size of the list, the number of segments, the number of segments to choose and the statistic number.
The second line contains $n$ integers $a_i$ ($1 \le a_i \le 10^9$) — the values of the numbers in the list.
Each of the next $s$ lines contains two integers $l_i$ and $r_i$ ($1 \le l_i \le r_i \le n$) — the endpoints of the segments.
It is possible that some segments coincide.
Output
Print exactly one integer — the smallest possible $k$-th order statistic, or -1 if it’s impossible to choose segments in a way that the multiset contains at least $k$ elements.
Examples
input
4 3 2 2
3 1 3 2
1 2
2 3
4 4
output
2
input
5 2 1 1
1 2 3 4 5
2 4
1 5
output
1
input
5 3 3 5
5 5 2 1 1
1 2
2 3
3 4
output
-1
Note
In the first example, one possible solution is to choose the first and the third segment. Together they will cover three elements of the list (all, except for the third one). This way the $2$-nd order statistic for the covered elements is $2$.
Solution:
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(0); int n, s, m, k; cin >> n >> s >> m >> k; vector<int> a(n); for (int i = 0; i < n; i++) { cin >> a[i]; } vector<pair<int,int>> seg(s); for (int i = 0; i < s; i++) { cin >> seg[i].first >> seg[i].second; seg[i].first--; seg[i].second--; } sort(seg.begin(), seg.end()); for (int i = 1; i < (int) seg.size(); i++) { if (seg[i].second <= seg[i - 1].second) { seg.erase(seg.begin() + i); i--; } } s = (int) seg.size(); m = min(m, s); const int inf = (int) 1.01e9; int low = 0, high = inf; while (low < high) { int mid = (low + high) >> 1; vector<int> pref(n + 1); for (int i = 0; i < n; i++) { pref[i + 1] = pref[i] + (a[i] <= mid); } vector<int> dp(s), new_dp(s); vector<int> value(s); vector<int> que; for (int take = 1; take <= m; take++) { int j = 0; int before = 0; que.clear(); int ptr = 0; for (int i = 0; i < s; i++) { while (j < i && seg[j].second < seg[i].first) { before = max(before, dp[j]); if (ptr < (int) que.size() && que[ptr] == j) { ptr++; } j++; } new_dp[i] = before + pref[seg[i].second + 1] - pref[seg[i].first]; if (ptr < (int) que.size()) { new_dp[i] = max(new_dp[i], value[que[ptr]] + pref[seg[i].second + 1]); } value[i] = dp[i] - pref[seg[i].second + 1]; while ((int) que.size() > ptr && value[i] >= value[que.back()]) { que.pop_back(); } que.push_back(i); } swap(dp, new_dp); } int cur = *max_element(dp.begin(), dp.end()); if (cur >= k) { high = mid; } else { low = mid + 1; } } cout << (low == inf ? -1 : low) << '\n'; return 0; }