AtCoder problem 006

C++ solution:
/*
競プロ典型90問　第6問　s
https://atcoder.jp/contests/typical90/submissions/23191468
*/
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>

using namespace std;

typedef long long ll;
typedef pair<char, int> P;

int N, K;
string s;

int main()
{

	cin >> N >> K;
	cin >> s;

	priority_queue<P, vector<P>, greater<P>> pq;
	//前からN - K + 1個をまず入れる。
	for (int i = 0; i < N - K + 1; i++)
		pq.push(make_pair(s[i], i));

	string ans = "";
	int topIdx = -1;
	for (int i = 0; i < K; i++)
	{
		P top;
		while (true)
		{
			top = pq.top();
			pq.pop();
			if (top.second > topIdx)
				break;
		}
		ans += top.first;
		topIdx = top.second;
		pq.push(make_pair(s[N - K + 1 + i], N - K + 1 + i));
	}
	cout << ans << endl;

	return 0;
}


Python solution: # でつoO(YOU PLAY WITH THE CARDS YOU'RE DEALT..)
def main():
    N, K = map(int, input().split())
    S = input()
    a = ord('a')
    st = SegmentTree(
        f=min, identity_factory=lambda: (
            27, len(S)), initial_values=[
            (ord(s) - a, i) for i, s in enumerate(S)])
    ans = []
    l = 0
    r = len(S) - K
    for _ in range(K):
        mn = st.query(l, r + 1)
        ans.append(mn[0])
        l = mn[1] + 1
        r += 1
    print(''.join(map(lambda x: chr(x + a), ans)))

class SegmentTree:
    __slots__ = ('__n', '__d', '__f', '__e')

    def __init__(self, n=None, f=max, identity_factory=int, initial_values=None):
        assert(n or initial_values)
        size = n if n else len(initial_values)
        d = [identity_factory() for _ in range(2 * size + 1)]
        self.__n, self.__d, self.__f, self.__e = size, d, f, identity_factory
        if initial_values:
            for i, v in enumerate(initial_values): d[size + i] = v
            for i in range(size - 1, 0, -1): d[i] = f(d[i << 1], d[i << 1 | 1])

    def get_at(self, index):
        return self.__d[index + self.__n]

    def set_at(self, index, new_value):
        i, d, f = index + self.__n, self.__d, self.__f
        if d[i] == new_value: return
        d[i], i = new_value, i >> 1
        while i: d[i], i = f(d[i << 1], d[i << 1 | 1]), i >> 1

    def modify_at(self, index, value):
        self.set_at(index, self.__f(self.__d[index + self.__n], value))

    def query(self, from_inclusive, to_exclusive):
        ans = self.__e()
        if to_exclusive <= from_inclusive: return ans
        l, r, d, f = from_inclusive + self.__n, to_exclusive + self.__n, self.__d, self.__f
        while l < r:
            if l & 1: ans, l = f(ans, d[l]), l + 1
            if r & 1: ans, r = f(d[r - 1], ans), r - 1
            l, r = l >> 1, r >> 1
        return ans

    def query_all(self):
        return self.__d[1]

    def bisect_left(self, func, from_inclusive=None, to_exclusive=None):
        '''func()がTrueになるもっとも左のindexを探す
        '''
        n, f, d, v = self.__n, self.__f, self.__d, self.__e()
        l = (from_inclusive if from_inclusive else 0) + n
        r = (to_exclusive if to_exclusive else n) + n
        h = 0
        while l < r:
            if l & 1:
                nv = f(v, d[l])
                if func(nv): return self.__single_bisect_left(func, l, v)
                v, l = nv, l + 1
            l, r, h = l >> 1, r >> 1, h + 1
        if r == 0: return n
        for i in range(h, 0, -1):
            if ((r + 1) << i <= n + n):
                nv = f(v, d[r])
                if func(nv): return self.__single_bisect_left(func, r, v)
                v, r = nv, r + 1
            r <<= 1
        return n

    def __single_bisect_left(self, func, root, left_val):
        n, f, d = self.__n, self.__f, self.__d
        i, v = root, left_val
        while i < n:
            i <<= 1
            nv = f(v, d[i])
            if not func(nv): i, v = i + 1, nv
        return i - n

if __name__ == '__main__':
    main()