#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
struct segTree{
int l,r;
int sum;
int lz;
}tree[400005];
int a[100005];
void build(int id,int l,int r){
tree[id].l=l;
tree[id].r=r;
tree[id].lz=-1;
if(l==r){
tree[id].sum=a[l];
return;
}
int mid,lc,rc;
mid=(l+r)/2;
lc=2*id,rc=2*id+1;
build(lc,l,mid);
build(rc,mid+1,r);
tree[id].sum=tree[lc].sum+tree[rc].sum;
}
void lazy(int id,int val){
tree[id].lz=val;
tree[id].sum=val*(tree[id].r-tree[id].l+1);
}
void pushup(int id){
tree[id].sum=tree[2*id].sum+tree[2*id+1].sum;
}
void pushdown(int id,int val){
lazy(2*id,val);
lazy(2*id+1,val);
tree[id].lz=-1;
}
void update(int id,int l,int r,int val){
if(l<=tree[id].l&&r>=tree[id].r)
return lazy(id,val);
if(tree[id].lz!=-1)
pushdown(id,tree[id].lz);
int mid,lc,rc;
mid=(tree[id].l+tree[id].r)/2;
lc=2*id,rc=2*id+1;
if(l<=mid)
update(lc,l,r,val);
if(r>mid)
update(rc,l,r,val);
pushup(id);
}
int query(int id,int l,int r){
if(l<=tree[id].l&&r>=tree[id].r)
return tree[id].sum;
if(tree[id].lz!=-1)
pushdown(id,tree[id].lz);
int mid,lc,rc,sum=0;
mid=(tree[id].l+tree[id].r)/2;
lc=2*id,rc=2*id+1;
if(l<=mid)
sum+=query(lc,l,r);
if(r>mid)
sum+=query(rc,l,r);
return sum;
}
char s[100005],t[100005];
int n,m;
struct question{
int l,r;
int k;
}Q[50005];
void solve(char c){
memset(a,0,sizeof(a));
memset(tree,0,sizeof(tree));
for(int i=1;i<=n;i++)
if(s[i]>c)
a[i]=1;
build(1,1,n);
for(int i=1;i<=m;i++){
int l=Q[i].l,r=Q[i].r;
int opt=Q[i].k;
if(l>r)
swap(l,r);
int sum=query(1,l,r),mid;
if(opt){
mid=r-sum;
update(1,l,mid,0);
update(1,mid+1,r,1);
}else{
mid=l+sum-1;
update(1,l,mid,1);
update(1,mid+1,r,0);
}
}
for(int i=1;i<=n;i++)
if(!query(1,i,i)&&!t[i])
t[i]=c;
}
int main(){
scanf("%d%d",&n,&m);
scanf("%s",s+1);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&Q[i].l,&Q[i].r,&Q[i].k);
for(char c='a';c<='z';c++)
solve(c);
for(int i=1;i<=n;i++)
printf("%c",t[i]);
printf("\n");
return 0;
}