【驭风计划 算法训练营】习题2-3:最小交换、楼尔邦德、最短路

最小交换


时间限制:4 sec

空间限制:256 MB

问题描述

给定一个 1 到 n 的排列(即一个序列,其中 [1,n] 之间的正整数每个都出现了恰好 1 次)。

你可以花 1 元钱交换两个相邻的数。

现在,你希望把它们升序排序。求你完成这个目标最少需要花费多少元钱。

输入格式

第一行一个整数 n,表示排列长度。

接下来一行 n 个用空格隔开的正整数,描述这个排列。

输出格式

输出一行一个非负整数,表示完成目标最少需要花多少元钱。

样例输入

3
3 2 1

样例输出

3

样例解释

你可以:

花 1 元交换 1,2,序列变成 3 1 2

花 1 元交换 1,3,序列变成 1 3 2

花 1 元交换 2,3,序列变成 1 2 3

总共需要花 3 元。

可以证明不存在更优的解。

数据范围

对于 20% 的数据,保证 n<=7。

对于 60% 的数据,保证 n<=1,000。

对于 100% 的数据,保证 n<=200,000。

提示

[每次交换相邻的两个数都会使逆序对 +1 或 -1。]

[逆序对数目不为零时,一定存在相邻的逆序对。]

[因此最优策略显然是每次都让逆序对数目 -1。]

[所以答案即为逆序对数目。]

[朴素的算法时间复杂度是 O(n^2) 的。]

[用归并排序求逆序对数可以通过本题。需要提醒的是,答案可能超过 32 位整数的范围哦。]

[逆序对数目同样可以用树状数组优化朴素的 O(n^2) 算法,并获得和归并排序相同的时间复杂度。有兴趣的同学可以自行学习。]

另外,为了帮助大家完成题目,我们提供了只包含了输入输出功能的程序模板,也提供了含有算法的大部分实现细节的程序。

你可以根据自己的实际情况,在这些程序的基础上进行作答,或不参考这些程序,这将与你的得分无关。

楼尔邦德


时间限制:2 sec

空间限制:256 MB

问题描述

给定包含 n 个数的序列 A。

再给出 Q 个询问,每个询问包含一个数 x,询问的是序列 A 中不小于 x 的最小整数是多少(无解输出-1)。

输入格式

第一行一个数 n,表示序列长度。

第二行 n 个用空格隔开的正整数,描述序列中的每一个元素。保证这些元素都不会超过 10^9。

第三行一个正整数 Q,表示询问个数。

接下来 Q 行,每行一个正整数 x,描述一个询问。

输出格式

输出 Q 行依次回答 Q 个询问,每行一个正整数,表示对应询问的答案。

样例输入

3
3 2 5
6
1
2
3
4
5
6

样例输出

2
2
3
5
5
-1

数据范围

对于 50% 的数据,保证 n<=2000。

对于 100% 的数据,保证 n<=300,000。

提示

[如果我们先将原序列排序,那么我们就可以在它上面进行二分查找啦!]

[STL库中有二分查找的函数__std::lower_bound__,你可以学习一下它的使用。当然啦,作为初学者,还是建议自己实现二分查找哦!]

另外,为了帮助大家完成题目,我们提供了只包含了输入输出功能的程序模板,也提供了含有算法的大部分实现细节的程序。

你可以根据自己的实际情况,在这些程序的基础上进行作答,或不参考这些程序,这将与你的得分无关。

最短路


时间限制:4 sec

空间限制:256 MB

问题描述

给定一张 n 个点的无向带权图,节点的编号从 1 至 n,求从 S 到 T 的最短路径长度。

输入格式

第一行 4 个数 n,m,S, T,分别表示点数、边数、起点、终点。

接下来 m 行,每行 3 个正整数 u,v,w,描述一条 u 到 v 的双向边,边权为 w。

保证 1<=u,v<=n。

输出格式

输出一行一个整数,表示 S 到 T 的最短路。

样例输入

7 11 5 4
2 4 2
1 4 3
7 2 2
3 4 3
5 7 5
7 3 3
6 1 1
6 3 4
2 4 3
5 6 3
7 2 1

数据范围

本题共设置 12 个测试点。

对于前 10 个测试点,保证 n<=2500,m<=6200,对于每条边有 w<=1000。这部分数据有梯度。

对于所有的 12 个测试点,保证 n<=100,000,m<=250,000。

提示

[本题是 Dijkstra 算法的模板练习题。]

[使用朴素的 Dijkstra 算法可以通过前 10 个测试点。]

[使用堆或__std::priority_queue__优化的 Dijkstra 算法可以通过所有测试点。]

另外,为了帮助大家完成题目,我们提供了只包含了输入输出功能的程序模板,也提供了含有算法的大部分实现细节的程序。

你可以根据自己的实际情况,在这些程序的基础上进行作答,或不参考这些程序,这将与你的得分无关。

完整代码私信

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值