Segments on the Line

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;
}