题目连接:
题目大意:
给出一个字母的序列(只包含小写字母),每次对它的一个区间进行排序,问最后的字母序列。
题目分析:
首先因为字母的数量很小,我们很容易想到统计统计排序这个O(26*log(n))的排序方法,对于每个要排序的区间,我们只需要从小到大统计每个字母有多少个,然后顺序输出即可,利用26棵线段树维护,可以做到O(logn)的复杂度。最后输出即可,总的复杂度O(26*n*logn)
AC代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#define MAX 100007
using namespace std;
int n,q;
char s[MAX];
struct Tree
{
int sum,l,r,lazy;
};
struct SegmentTree
{
Tree tree[MAX<<2];
void push_up ( int u )
{
tree[u].sum = tree[u<<1].sum + tree[u<<1|1].sum;
}
void push_down ( int u )
{
int lazy = tree[u].lazy;
if ( lazy != -1 )
{
tree[u<<1].lazy = tree[u<<1|1].lazy = lazy;
tree[u<<1].sum = (tree[u<<1].r-tree[u<<1].l+1)*lazy;
tree[u<<1|1].sum = (tree[u<<1|1].r-tree[u<<1|1].l+1)*lazy;
tree[u].lazy = -1;
}
}
void build ( int u , int l , int r , int a )
{
tree[u].l = l;
tree[u].r = r;
tree[u].lazy = -1;
if ( l == r )
{
if ( s[l]-'a' == a ) tree[u].sum = 1;
else tree[u].sum = 0;
return;
}
int mid = l+r>>1;
build ( u<<1 , l , mid , a );
build ( u<<1|1 , mid+1 , r , a );
push_up ( u );
}
void update ( int u , int left , int right , int v )
{
int l = tree[u].l;
int r = tree[u].r;
int mid = l+r>>1;
if ( left <= l && r <= right )
{
tree[u].sum = (r-l+1)*v;
tree[u].lazy = v;
return;
}
push_down ( u );
if ( left <= mid && right >= l )
update ( u<<1 , left , right , v );
if ( left <= r && right > mid )
update ( u<<1|1 , left , right , v );
push_up ( u );
}
int query ( int u , int left , int right )
{
int l = tree[u].l;
int r = tree[u].r;
int mid = l+r>>1;
if ( left <= l && r <= right )
return tree[u].sum;
push_down ( u );
int ret = 0;
if ( left <= mid && right >= l )
ret += query ( u<<1 , left , right );
if ( left <= r && right > mid )
ret += query ( u<<1|1 , left , right );
return ret;
}
}segmentTree[26];
inline void print ( )
{
for ( int i = 1 ; i <= n ; i++ )
for ( int j = 0 ; j < 26 ; j++ )
if ( segmentTree[j].query ( 1 , i , i ) )
{
putchar ( (char)(j+'a') );
break;
}
puts ( "" );
}
int main ( )
{
int x,y,z;
int num[26];
while ( ~scanf ( "%d%d" , &n , &q ) )
{
scanf ("%s" , s+1 );
for ( int i = 0 ; i < 26 ; i++ )
segmentTree[i].build ( 1 , 1 , n , i );
while ( q-- )
{
//print ();
scanf ( "%d%d%d" , &x , &y , &z );
memset ( num , 0 , sizeof ( num ));
for ( int i = 0 ; i < 26 ; i++ )
{
num[i] = segmentTree[i].query( 1 , x , y );
segmentTree[i].update ( 1 , x , y , 0 );
}
int l = x;
if ( z )
{
for ( int i = 0 ; i < 26 ; i++ )
{
segmentTree[i].update ( 1 , l , l+num[i]-1 , 1 );
l = l+num[i];
}
}
else
{
for ( int i = 25 ; i >= 0 ; i-- )
{
segmentTree[i].update ( 1 , l , l+num[i]-1 , 1 );
l = l+num[i];
}
}
}
print ();
/*for ( int i = 1 ; i <= n ; i++ )
for ( int j = 0 ; j < 26 ; j++ )
if ( segmentTree[j].query ( 1 , i , i ) )
{
putchar ( (char)(j+'a') );
break;
}
puts ( "" );*/
}
}