天天看点

计数排序 + 线段树优化 --- Codeforces 558E : A Simple Task E. A Simple Task Problem's Link: http://codeforces.com/problemset/problem/558/E

Mean: 

给定一个字符串,有q次操作,每次操作将(l,r)内的字符升序或降序排列,输出q次操作后的字符串。

analyse:

所谓计数排序,是对一个元素分布较集中的数字集群进行排序的算法,时间复杂度为O(n),但使用条件很苛刻。首先对n个数扫一遍,映射出每个数字出现的次数,然后再O(n)扫一遍处理出:对于数字ai,有多少个数字在ai前面。有了这个信息,我们就可以在O(1)的时间内确定出排序后ai所在的位置。

解题思路:

对于每个Query,我们先统计出(l,r)区间内每个字母出现的次数,然后分类来排序(非升或非降)。这个更新操作就相当于:

但是每次这样去统计时间复杂度是O(n),对于(10^5)*(5*10^4)的时间复杂度势必超时。所以我们需要一种在区间更新和统计上时间复杂度都客观的数据结构---线段树。

我们开26棵线段树,第i棵线段树维护的是:26个字母中排第i个的字母在各个区间的数目。

这样一来,我们就可以将一个字符串S完美的融入到这26棵线段树中去,更新和查找都从上面的O(n)变为了O(logn)。其中传递更新需要用Lazy标记。

Time complexity: O(q*logn*sz)

Source code: 

继续阅读