This task is very simple. Given a string *S* of length *n* and *q* queries each query is on the format *i* *j* *k* which means sort the substring consisting of the characters from *i* to *j* in non-decreasing order if *k* = 1 or in non-increasing order if *k* = 0.

Output the final string after applying the queries.
The first line will contain two integers *n*, *q* (1 ≤ *n* ≤ 10<sup class="upper-index">5</sup>, 0 ≤ *q* ≤ 50 000), the length of the string and the number of queries respectively. 

Next line contains a string *S* itself. It contains only lowercase English letters.

Next *q* lines will contain three integers each *i*, *j*, *k* (1 ≤ *i* ≤ *j* ≤ *n*, <img align="middle" class="tex-formula" src="https://espresso.codeforces.com/187c38b0d200dfc5b5249f93c000f8dee9c1180d.png" style="max-width: 100.0%;max-height: 100.0%;"/>).
import sys
import os
from operator import add
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
    newlines = 0

    def __init__(self, file):
        self._fd = file.fileno()
        self.buffer = BytesIO()
        self.writable = "x" in file.mode or "r" not in file.mode
        self.write = self.buffer.write if self.writable else None

    def read(self):
        while True:
            b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
            if not b:
                break
            ptr = self.buffer.tell()
            self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr)
        self.newlines = 0
        return self.buffer.read()

    def readline(self):
        while self.newlines == 0:
            b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
            self.newlines = b.count(b"\n") + (not b)
            ptr = self.buffer.tell()
            self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr)
        self.newlines -= 1
        return self.buffer.readline()

    def flush(self):
        if self.writable:
            os.write(self._fd, self.buffer.getvalue())
            self.buffer.truncate(0), self.buffer.seek(0)


class IOWrapper(IOBase):
    def __init__(self, file):
        self.buffer = FastIO(file)
        self.flush = self.buffer.flush
        self.writable = self.buffer.writable
        self.write = lambda s: self.buffer.write(s.encode("ascii"))
        self.read = lambda: self.buffer.read().decode("ascii")
        self.readline = lambda: self.buffer.readline().decode("ascii")


sys.stdin, sys.stdout = IOWrapper(sys.stdin), IOWrapper(sys.stdout)
input = lambda: sys.stdin.readline().rstrip("\r\n")

def readList():
    return list(map(int, input().split()))
def readInt():
    return int(input())
def readInts():
    return map(int, input().split())
def readStr():
    return input().strip()


class LazySegTree:
    def _update(self, k):
        self.d[k] = self.op(self.d[2 * k], self.d[2 * k + 1])

    def _all_apply(self, k, f):
        self.d[k] = self.mapping(f, self.d[k], self.length[k])
        if k < self.size:
            self.lz[k] = self.composite(f, self.lz[k])

    def _push(self, k):
        self._all_apply(2 * k, self.lz[k])
        self._all_apply(2 * k + 1, self.lz[k])
        self.lz[k] = self.identity

    def mapping(self, a, x, l):
        if a == -1:
            return x
        if a == 0:
            return 0
        return l

    def composite(self, a, b):
        return a if a >= 0 else b

    def __init__(self, V, OP, E):
        self.n = len(V)
        self.log = (self.n - 1).bit_length()
        self.size = 1 << self.log
        self.d = [E for i in range(2 * self.size)]
        self.length = [0] * (2 * self.size)
        self.e = E
        self.op = OP
        self.identity = -1
        self.lz = [-1] * self.size
        for i in range(self.n):
            self.d[self.size + i] = V[i]
            self.length[self.size + i] = 1
        for i in range(self.size - 1, 0, -1):
            self._update(i)
            self.length[i] = self.length[2 * i] + self.length[2 * i + 1]

    # assign x to point p w/ lazy prop
    def set(self, p, x):
        assert 0 <= p < self.n
        p += self.size
        for i in range(self.log, 0, -1):
            self._push(p >> i)
        self.d[p] = x
        for i in range(1, self.log + 1):
            self._update(p >> i)

    # query point p w/ lazy prop
    def get(self, p):
        assert 0 <= p < self.n
        p += self.size
        for i in range(self.log, 0, -1):
            self._push(p >> i)
        return self.d[p]

    # query range l, r w/ lazy prop
    def prod(self, l, r):
        assert 0 <= l <= r <= self.n
        if l == r:
            return self.e
        l += self.size
        r += self.size
        for i in range(self.log, 0, -1):
            if ((l >> i) << i) != l:
                self._push(l >> i)
            if ((r >> i) << i) != r:
                self._push(r >> i)
        sml, smr = self.e, self.e
        while l < r:
            if l & 1:
                sml = self.op(sml, self.d[l])
                l += 1
            if r & 1:
                r -= 1
                smr = self.op(self.d[r], smr)
            l >>= 1
            r >>= 1
        return self.op(sml, smr)

    # query the whole array a[1...n]
    def all_prod(self):
        return self.d[1]

    # update point w/ lazy prop ?
    def apply_point(self, p, f):
        assert 0 <= p < self.n
        p += self.size
        for i in range(self.log, 0, -1):
            self._push(p >> i)
        self.d[p] = self.mapping(f, self.d[p], self.length[p])  # set to 1 (length[p]) instead of set to f?
        for i in range(1, self.log + 1):
            self._update(p >> i)

    # update query w/ lazy prop
    def apply(self, l, r, f):
        assert 0 <= l <= r <= self.n
        if l == r:
            return
        l += self.size
        r += self.size
        for i in range(self.log, 0, -1):
            if ((l >> i) << i) != l:
                self._push(l >> i)
            if ((r >> i) << i) != r:
                self._push((r - 1) >> i)
        l2, r2 = l, r
        while l < r:
            if l & 1:
                self._all_apply(l, f)
                l += 1
            if r & 1:
                r -= 1
                self._all_apply(r, f)
            l >>= 1
            r >>= 1
        l, r = l2, r2
        for i in range(1, self.log + 1):
            if ((l >> i) << i) != l:
                self._update(l >> i)
            if ((r >> i) << i) != r:
                self._update((r - 1) >> i)

    def max_right(self, l, g):
        assert 0 <= l <= self.n
        assert g(self.e)
        if l == self.n:
            return self.n
        l += self.size
        for i in range(self.log, 0, -1):
            self._push(l >> i)
        sm = self.e
        while 1:
            while i % 2 == 0:
                l >>= 1
            if not (g(self.op(sm, self.d[l]))):
                while l < self.size:
                    self._push(l)
                    l = (2 * l)
                    if g(self.op(sm, self.d[l])):
                        sm = self.op(sm, self.d[l])
                        l += 1
                return l - self.size
            sm = self.op(sm, self.d[l])
            l += 1
            if (l & -l) == l: break
        return self.n

    def min_left(self, r, g):
        assert (0 <= r <= self.n)
        assert g(self.e)
        if r == 0:
            return 0
        r += self.size
        for i in range(self.log, 0, -1):
            self._push((r - 1) >> i)
        sm = self.e
        while 1:
            r -= 1
            while r > 1 and (r % 2): r >>= 1
            if not (g(self.op(self.d[r], sm))):
                while r < self.size:
                    self._push(r)
                    r = (2 * r + 1)
                    if g(self.op(self.d[r], sm)):
                        sm = self.op(self.d[r], sm)
                        r -= 1
                return r + 1 - self.size
            sm = self.op(self.d[r], sm)
            if (r & -r) == r:
                break
        return 0

# BF, EC, DB, CC, CL
def solve():
    n, q = readInts()
    s = [ord(c) - ord("a") for c in readStr()]
    seg = [LazySegTree([v == i for v in s], add, 0) for i in range(26)]
    for _ in range(q):
        i, j, k = readInts()
        freq = [seg[x].prod(i-1, j) for x in range(26)]
        f, b = i-1, j-1
        for x in range(26):
            if freq[x]:
                seg[x].apply(i - 1, j, 0)
                if k:
                    seg[x].apply(f, f + freq[x], 1)
                    f += freq[x]
                else:
                    seg[x].apply(b+1-freq[x], b+1, 1)
                    b -= freq[x]

    ans = []
    for i in range(n):
        for j in range(26):
            if seg[j].prod(i, i+1):
                ans.append(chr(j + ord("a")))
    return "".join(ans)

print(solve())