Codeforces-1288E Messenger Simulator
题目大意:
给定一个n的identity permutation。m个操作,每次把给定的一个数字移到第一个位置。求每个数字在整个过程中所处的最小位置和最大位置。
1<=n,m<3e5
题目解法:
显然,对于没有被移动过的数,它的最小位置就是它本身。否则它的最小位置是1。
考虑操作序列中前后最近的两个相同的数字。令这个数字为x。这个以x开始以x结尾的区间为[l,r]。我们可以发现在这一系列操作中,x先被放在了第一个,然后不停的被往右移动,直到再次被移到第一个。在这个过程中,x移动的数量是[l,r]中不同数字的数量。强调不同数字是因为如果一个数字已经被移到x前面了,那它后面的所有移动都与x无关了。
再考虑如果数字x为第一次出现,那么显然只有比它大的数字的移动才会影响它的位置。因为每次移动都是在向前移动的。比x小的数字是不可能在x移动前被移到x后面的。同样这里也需要强调不同的数字,即每个比x大的数字只计算一次。
那么问题就转化为了两个问题:1.求区间[1,l]中比a[l]大的数有几个 2.求区间[l.r]中有多少个不同的数
令ans[x]为数字x的最大位置,lst[i]为位置i上一个和它数字一样的位置。
对于第一个问题,我们设res[i]为目前为止比i大的数字的数量。显然,当我们在遍历操作序列时,如果当前数字x是第一次出现的,那么res[x+1~n]都要加1,同时我们用res[x]的值更新ans[x]。可以运用bit维护差分数组得到res。
对于第二个问题,我们设left[i]为以i为左端点到目前为止重复的数字的个数。显然,因为我们所关注的区间的右端点一直是跟随着我们的遍历移动的,答案就是r-l-1-left[l]。对于每个位置i,假如该位置上的数字已经不是首次出现,那么如果区间的左端点在上一个出现的位置左边,那么就会都一个重复的数字,即left[1~lst[i]]都要加1。这同样可以运用bit维护查分数组得到。
因此,我们可以用两个树状数组解决这道题。复杂度是O(n*(log(n*m))

浙公网安备 33010602011771号