【cqoi2011】动态逆序对

博客详细讨论了如何在序列中动态计算逆序对数的问题,包括输入输出格式、样例以及数据范围。提到了五种不同的算法实现,包括树套树、分块+排序、分块+bit、CDQ分治以及持续化线段树,其中CDQ分治的优化版本代码被给出。文章着重于算法的时间复杂度和常数优化,强调了各种方法的优缺点和适用场景。
摘要由CSDN通过智能技术生成
时间限制:1秒  内存限制:64M

【问题描述】

  对于序列A[i],它的逆序对数定义为满足:i < j,且A[i] > A[j]的数对(i,j)的个数。

  给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数。

【输入格式】

  输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数。以下n行每行包含一个1到n之间的正整数,即初始排列。以下m行每行一个正整数,依次为每次删除的元素。

【输出格式】

  输出包含m行,依次为删除每个元素之前,逆序对的个数。

【输入样例】

5 4
1
5
3
4
2
5
1
4
2

【输出样例】

5
2
2
1

【数据范围】

编号  1-2   3-4    5-6   7-8    9-10
n   <=1000  <=30000 <=50000 <=60000 <=100000
m   <=100   <=10000 <=20000 <=40000 <=50000

【来源】

(1,5,3,4,2) -> (1,3,4,2) -> (3,4,2) -> (3,2) -> (3)。

今天晚上一直在做这道题,做了几种方法出来,但时间复杂度各不相同,准确的说只是常数不同,但就是这个常数有2种方法看起来可以却要被卡住1~2个点。

第一种方法:树套树,常数极高,可能是因为我用的线段树套平衡树,线段树的常数大了点。

第二种:分块+排序,普通的分块方法,就按照要求,分成几块,然后块内排序。删除就找前面比他大的和后面比他小的就好。会卡常数一个点。

第三种:分块+bit,也是分块,而且这种方法也要优化才能过,用bit记录块内的值,bit[i][j]前i个块一共有多少个在j所属的范围内。这个前缀和的思想可以省很多时间。

第四种:CDQ分治,也要优化,优化了特别快,没有优化特别慢,最可怕的是不容易看出来优化在哪里。

第五种:持续化线段树:思想和分块加bit的优化版差不多。

这里我提供一下CDQ分治的代码(因为难想),一个优化了的,一个没优化的,其他代码就不给了,请读者自己好好写,都不难但是请主要细节。

#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值