/*******************************************************
3) Amazon OA — k-th Smallest in Every Window of Length m
Problem:
- For each sliding window of size m, output the k-th smallest element.
Idea:
- Keep two multisets:
small = k smallest numbers in window
big = remaining numbers
- Then k-th smallest = max(small)
Time: O(n log m)
*******************************************************/
#include <bits/stdc++.h> // standard CP header
using namespace std; // use std names directly
static void rebalance(multiset<long long>& small, multiset<long long>& big, int k) { // keep sets valid
while ((int)small.size() > k) { // if small has too many
auto it = prev(small.end()); // iterator to largest in small
big.insert(*it); // move it to big
small.erase(it); // remove from small
}
while ((int)small.size() < k && !big.empty()) { // if small has too few and big has elements
auto it = big.begin(); // iterator to smallest in big
small.insert(*it); // move it to small
big.erase(it); // remove from big
}
while (!small.empty() && !big.empty()) { // if both sets non-empty
auto itSmallMax = prev(small.end()); // max element in small
auto itBigMin = big.begin(); // min element in big
if (*itSmallMax <= *itBigMin) break; // order is fine, stop
long long a = *itSmallMax; // value from small that is too large
long long b = *itBigMin; // value from big that is too small
small.erase(itSmallMax); // remove a
big.erase(itBigMin); // remove b
small.insert(b); // put b into small
big.insert(a); // put a into big
}
}
int main() { // program start
ios::sync_with_stdio(false); // fast I/O
cin.tie(nullptr); // fast I/O
int n, m, k; // n=array size, m=window size, k=order statistic
cin >> n >> m >> k; // read them
vector<long long> a(n); // array values
for (int i = 0; i < n; i++) cin >> a[i]; // read array
multiset<long long> small, big; // the two multisets
for (int i = 0; i < m; i++) { // insert first window
big.insert(a[i]); // put everything in big first
}
rebalance(small, big, k); // then move smallest k into small properly
auto print_ans = [&]() { // helper lambda to print k-th smallest
cout << *prev(small.end()); // k-th smallest is maximum of small
};
print_ans(); // print answer for first window
for (int i = m; i < n; i++) { // slide window from i=m to n-1
long long out = a[i - m]; // element leaving the window
long long in = a[i]; // element entering the window
auto itSmall = small.find(out); // try to find outgoing element in small
if (itSmall != small.end()) { // if found in small
small.erase(itSmall); // erase it
} else { // else it must be in big
auto itBig = big.find(out); // find in big
if (itBig != big.end()) big.erase(itBig); // erase it if found
}
if (!small.empty() && in <= *prev(small.end())) { // if incoming likely belongs in small
small.insert(in); // insert into small
} else { // otherwise
big.insert(in); // insert into big
}
rebalance(small, big, k); // restore invariants
cout << " "; // space between answers
print_ans(); // print current window answer
}
cout << "\n"; // newline at end
return 0; // done
}