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.
Input
The first line will contain two integers n, q (1 ≤ n ≤ 105, 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, ).
Output
Output one line, the string S after applying the queries.
Examples
Input
10 5
abacdabcda
7 10 0
5 8 1
1 4 0
3 6 0
7 10 1
Output
cbcaaaabdd
Input
10 1
agjucbvdfk
1 10 1
Output
abcdfgjkuv
Note
First sample test explanation:
题意:
给出一个字符串,两种操作,操作0,将l-r区间降序排序,操作1,将l-r区间升序排序。
输出经过所有操作后的字符串
题解:
建26棵线段树,区间查询个数,点修改,对于每个操作,升序从1-26计数排序,降序从26-1计数排序
最后单点查询
代码如下:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define lson root<<1 #define rson root<<1|1 using namespace std; struct oper { int l,r; } op[26]; struct seg_tree { struct node { int l,r,lazy,sum; } tr[400010]; void push_up(int root) { tr[root].sum=tr[lson].sum+tr[rson].sum; } void push_down(int root) { int mid=(tr[root].l+tr[root].r)>>1; tr[lson].sum=(mid-tr[root].l+1)*tr[root].lazy; tr[lson].lazy=tr[root].lazy; tr[rson].sum=(tr[root].r-mid)*tr[root].lazy; tr[rson].lazy=tr[root].lazy; tr[root].lazy=-1; } void build(int root,int l,int r) { if(l==r) { tr[root].l=l; tr[root].r=r; tr[root].lazy=-1; return ; } int mid=(l+r)>>1; tr[root].l=l; tr[root].r=r; tr[root].lazy=-1; build(lson,l,mid); build(rson,mid+1,r); } void update(int root,int l,int r,int val) { if(l>r) { return ; } if(tr[root].l==l&&tr[root].r==r) { tr[root].sum=(tr[root].r-tr[root].l+1)*val; tr[root].lazy=val; return ; } if(~tr[root].lazy) { push_down(root); } int mid=(tr[root].l+tr[root].r)>>1; if(l>mid) { update(rson,l,r,val); } else { if(mid>=r) { update(lson,l,r,val); } else { update(lson,l,mid,val); update(rson,mid+1,r,val); } } push_up(root); } int query(int root,int l,int r) { if(tr[root].l==l&&tr[root].r==r) { return tr[root].sum; } if(~tr[root].lazy) { push_down(root); } int mid=(tr[root].l+tr[root].r)>>1; if(l>mid) { return query(rson,l,r); } else { if(mid>=r) { return query(lson,l,r); } else { return query(lson,l,mid)+query(rson,mid+1,r); } } } } tree[26]; char c[100010]; int main() { int n,m; scanf("%d %d",&n,&m); scanf("%s",c+1); for(register int i=0; i<26; ++i) { tree[i].build(1,1,n); } for(register int i=1; i<=n; ++i) { tree[c[i]-'a'].update(1,i,i,1); } int l,r,kd,he,ta; for(; m--;) { scanf("%d%d%d",&l,&r,&kd); ta=l-1; if(kd) { for(register int i=0; i<26; ++i) { he=ta+1; ta=he+tree[i].query(1,l,r)-1; op[i].l=he; op[i].r=ta; } } else { for(register int i=25; i>=0; --i) { he=ta+1; ta=he+tree[i].query(1,l,r)-1; op[i].l=he; op[i].r=ta; } } for(register int i=0; i<26; ++i) { if(op[i].l<=op[i].r) { tree[i].update(1,op[i].l,op[i].r,1); tree[i].update(1,l,op[i].l-1,0); tree[i].update(1,op[i].r+1,r,0); } } } for(register int i=1; i<=n; ++i) { for(register int j=0; j<26; ++j) { if(tree[j].query(1,i,i)) { putchar(j+97); break; } } } }