NOIP2013--火柴排队(树状数组)
转载:
树状数组,具体的说是 离散化+树状数组。这也是学习树状数组的第一题.
算法的大体流程就是:
1.先对输入的数组离散化,使得各个元素比较接近,而不是离散的,
2.接着,运用树状数组的标准操作来累计数组的逆序数。
算法详细解释:
1.解释为什么要有离散的这么一个过程?
刚开始以为999.999.999这么一个数字,对于int存储类型来说是足够了。
还有只有500000个数字,何必要离散化呢?
刚开始一直想不通,后来明白了,后面在运用树状数组操作的时候,
用到的树状数组C[i]是建立在一个有点像位存储的数组的基础之上的,
不是单纯的建立在输入数组之上。
比如输入一个9 1 0 5 4,那么C[i]树状数组的建立是在,
下标 0 1 2 3 4 5 6 7 8 9
数组 1 1 0 0 1 1 0 0 0 1
现在由于999999999这个数字相对于500000这个数字来说是很大的,
所以如果用数组位存储的话,那么需要999999999的空间来存储输入的数据。
这样是很浪费空间的,题目也是不允许的,所以这里想通过离散化操作,
使得离散化的结果可以更加的密集。
2. 怎么对这个输入的数组进行离散操作?
离散化是一种常用的技巧,有时数据范围太大,可以用来放缩到我们能处理的范围;
因为其中需排序的数的范围0---999 999 999;显然数组不肯能这么大;
而N的最大范围是500 000;故给出的数一定可以与1.。。。N建立一个一一映射;
①当然用map可以建立,效率可能低点;
②这里用一个结构体
struct Node
{
int v,ord;
}p[510000];和一个数组a[510000];
其中v就是原输入的值,ord是下标;然后对结构体按v从小到大排序;
此时,v和结构体的下标就是一个一一对应关系,而且满足原来的大小关系;
for(i=1;i<=N;i++) a[p[i].ord]=i;
然后a数组就存储了原来所有的大小信息;
比如 9 1 0 5 4 ------- 离散后aa数组就是 5 2 1 4 3;
具体的过程可以自己用笔写写就好了。
3. 离散之后,怎么使用离散后的结果数组来进行树状数组操作,计算出逆序数?
如果数据不是很大, 可以一个个插入到树状数组中,
每插入一个数, 统计比他小的数的个数,
对应的逆序为 i- getsum( aa[i] ),
其中 i 为当前已经插入的数的个数,
getsum( aa[i] )为比 aa[i] 小的数的个数,
i- sum( aa[i] ) 即比 aa[i] 大的个数, 即逆序的个数
但如果数据比较大,就必须采用离散化方法
假设输入的数组是9 1 0 5 4, 离散后的结果aa[] = {5,2,1,4,3};
在离散结果中间结果的基础上,那么其计算逆序数的过程是这么一个过程。
1,输入5, 调用upDate(5, 1),把第5位设置为1
1 2 3 4 5
0 0 0 0 1
计算1-5上比5小的数字存在么? 这里用到了树状数组的getSum(5) = 1操作,
现在用输入的下标1 - getSum(5) = 0 就可以得到对于5的逆序数为0。
2. 输入2, 调用upDate(2, 1),把第2位设置为1
1 2 3 4 5
0 1 0 0 1
计算1-2上比2小的数字存在么? 这里用到了树状数组的getSum(2) = 1操作,
现在用输入的下标2 - getSum(2) = 1 就可以得到对于2的逆序数为1。
3. 输入1, 调用upDate(1, 1),把第1位设置为1
1 2 3 4 5
1 1 0 0 1
计算1-1上比1小的数字存在么? 这里用到了树状数组的getSum(1) = 1操作,
现在用输入的下标 3 - getSum(1) = 2 就可以得到对于1的逆序数为2。
4. 输入4, 调用upDate(4, 1),把第5位设置为1
1 2 3 4 5
1 1 0 1 1
计算1-4上比4小的数字存在么? 这里用到了树状数组的getSum(4) = 3操作,
现在用输入的下标4 - getSum(4) = 1 就可以得到对于4的逆序数为1。
5. 输入3, 调用upDate(3, 1),把第3位设置为1
1 2 3 4 5
1 1 1 1 1
计算1-3上比3小的数字存在么? 这里用到了树状数组的getSum(3) = 3操作,
现在用输入的下标5 - getSum(3) = 2 就可以得到对于3的逆序数为2。
6. 0+1+2+1+2 = 6 这就是最后的逆序数
分析一下时间复杂度,首先用到快速排序,时间复杂度为O(NlogN),
后面是循环插入每一个数字,每次插入一个数字,分别调用一次upData()和getSum()
外循环N, upData()和getSum()时间O(logN) => 时间复杂度还是O(NlogN).
最后总的还是O(NlogN).
NOIP2013--火柴排队(树状数组)的更多相关文章
- 【BZOJ2141】排队 树状数组+分块
[BZOJ2141]排队 Description 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和.红星幼儿园的小朋友们排起了长长地队伍,准备 ...
- BZOJ2141 排队 树状数组 分块
原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ2141.html 题目传送门 - BZOJ2141 题意 给定一个序列 $a$ ,先输出原先的逆序对数. ...
- BZOJ2141排队——树状数组套权值线段树(带修改的主席树)
题目描述 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家 乐和和.红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们的身高有所区别 ...
- BZOJ 2141 排队(树状数组套主席树)
解法很多的题,可以块套树状数组,可以线段树套平衡树.我用的是树状数组套主席树. 题意:给出一段数列,m次操作,每次操作是交换两个位置的数,求每次操作后的逆序对数.(n,m<=2e4). 对于没有 ...
- [NOIP2013提高&洛谷P1966]火柴排队 题解(树状数组求逆序对)
[NOIP2013提高&洛谷P1966]火柴排队 Description 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相 ...
- [树状数组+逆序对][NOIP2013]火柴排队
火柴排队 题目描述 涵涵有两盒火柴,每盒装有n根火柴,每根火柴都有一个高度.现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定义为:∑ (ai-bi)2,i=1,2,3,. ...
- LOJ2609. NOIP2013 火柴排队 【树状数组】
LOJ2609. NOIP2013 火柴排队 LINK 题目大意: 给你两个数列,定义权值∑i=1(ai−bi)^2 问最少的操作次数,最小化权值 首先需要发现几个性质 最小权值满足任意i,j不存在a ...
- 火柴排队(NOIP2013)(附树状数组专题讲解(其实只是粗略。。。))
原题传送门 首先,这道题目是一道神奇的题. 看到这道题,第一眼就觉得2个数组排个序,然后一一对应的时候一定差值最小. 由于我们可以将这2个数列同时进行调换. 所以我们先把2个数列排个序. 第二个序列中 ...
- Codevs 3286 火柴排队 2013年NOIP全国联赛提高组 树状数组,逆序对
题目:http://codevs.cn/problem/3286/ 3286 火柴排队 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : ...
- P1966 火柴排队——逆序对(归并,树状数组)
P1966 火柴排队 很好的逆序对板子题: 求的是(x1-x2)*(x1-x2)的最小值: x1*x1+x2*x2-2*x1*x2 让x1*x2最大即可: 可以证明将b,c数组排序后,一一对应的状态是 ...
随机推荐
- C#——计时器的操作
我们可以用Stopwatch类获得程序的运行时间,在优化代码时,可以用此方法来查看优化前后程序所耗费的时间 static void Main(string[] args) { Stopwatch sw ...
- C# Task多线程
来自Eleven老师示例 private void btnTask_Click(object sender, EventArgs e) { Console.WriteLine(); Console.W ...
- select2下拉插件
下拉单选: 1.行内 1)初始化数据: <select class="form-control select5"> <option selected>张三1 ...
- 数据库操作(二)SOQL
1.SOQL SOQL是对象查询语言.它可以在单个sObject中在给定标准上搜索记录. 2.SELECT语句 [格式]SELECT 列名称 FROM 表名称 [示例] 3.SELECT...WHER ...
- java aop面向切面编程
最近一直在学java的spring boot,一直没有弄明白aop面向切面编程是什么意思.看到一篇文章写得很清楚,终于弄明白了,原来跟python的装饰器一样的效果.http://www.cnblog ...
- vino-server服务是啥服务
近期接手一个项目,开始梳理服务器,突然发现有个进程是开启5900远程桌面端口的, 在不知情的情况下怕被人给利用了,啥也不说,先干掉再说. server端开启vino-server,允许别人查看自己的桌 ...
- Luogu P1041 [2003NOIP提高组]传染病控制
P1041 传染病控制 题目背景 近来,一种新的传染病肆虐全球.蓬莱国也发现了零星感染者,为防止该病在蓬莱国大范围流行,该国政府决定不惜一切代价控制传染病的蔓延.不幸的是,由于人们尚未完全认识这种传染 ...
- gcc和gdb的基本操作
gcc和gdb yum 在线安装软件,使用阿里云镜像站,OPSX 选择你安装的系统 点帮助 查看配置命令行 yum --list | grep gdb #查找要安装的软件 yum install -y ...
- Tkinter图形界面设计(GUI)
[因为这是我第一个接触的GUI图形界面python库,现在也不用了,所以大多数内容都来自之前花 钱买的一些快速入门的内容,可以当作简单的知识点查询使用] 在此声明:内容来自微信公众号GitChat,付 ...
- [Codeforces 872]比赛记录
强行打了$cf$上的第一场比赛,现在感觉自己的$rating$会炸飞= = A 这是练习输入输出吗QAQ,竟然$WA$了两遍QAQ,我$WA$的一声就哭了出来啊QAQ B 好像很水的乱扫就好了,m ...