车厢调序耗电
拼多多 10月26号 笔试真题 第一题
拼多多真题目录点击查看: 拼多多笔试真题题库目录|笔试题库 + 算法考点详解
题目内容
多多在这座火车站担任调度。
今天驶入的货运列车一共挂了 L L L 节车厢,自左向右记作第 1 , 2 , ... , L 1,2,\dots,L 1,2,...,L 节。第 t t t 节所装货物的卸货等级记为 B t B_t Bt,各节的卸货等级两两不同。
为了让后面卸货更顺手,多多要把整列车厢排成卸货等级自左向右严格变大的样子。
站台上已经备好两套专用器具:
- 小型调转轨道:挑出紧挨着的 2 2 2 节车厢,把这两节的前后次序倒过来。这套设备体积很小,省力机构装不进去,只能靠电机带动,每开动一次就要用掉 1 1 1 个单位的电。
- 三节回旋轨道:挑出紧挨着的 3 3 3 节车厢,把这三节的前后次序整段倒过来。轨道配了加长摇柄和配重,调度员用不大的力气就能让它启动,所以完全不耗电。
这两种设备要用几次、谁先谁后,以及压在列车哪一段紧邻车厢上,多多都能自由安排。请算出排成上述目标次序时,最少要用掉多少单位的电。
输入描述
首行一个整数 Q Q Q( 1 ≤ Q ≤ 10 1 \le Q \le 10 1≤Q≤10),表示测试一共有几组。
后面共 Q Q Q 行,每一行对应一组。行首整数 L L L( 1 ≤ L ≤ 10 5 1 \le L \le 10^5 1≤L≤105)是本组车厢节数,随后 L L L 个整数 B 1 , B 2 , ... , B L B_1,B_2,\dots,B_L B1,B2,...,BL( 0 ≤ B t ≤ 10 9 0 \le B_t \le 10^9 0≤Bt≤109)是各节的卸货等级。全部 B t B_t Bt 彼此不相等,读进来的每个数都是整数。
输出描述
写出 Q Q Q 行,每行一个整数,对应该组最少消耗的电量。
样例1
输入
2
4 1 3 2 4
3 3 2 1
输出
1
0
说明
第一组卸货等级是 1 , 3 , 2 , 4 1,3,2,4 1,3,2,4。小型调转轨道把第 2 2 2 节和第 3 3 3 节倒序后得到 1 , 2 , 3 , 4 1,2,3,4 1,2,3,4,耗电 1 1 1。不耗电时,只能交换第 1 1 1 节与第 3 3 3 节,或者交换第 2 2 2 节与第 4 4 4 节。交换之后奇数位仍是 1 1 1 和 2 2 2,而目标次序的奇数位是 1 1 1 和 3 3 3,所以耗电不能是 0 0 0。
第二组卸货等级是 3 , 2 , 1 3,2,1 3,2,1。三节回旋轨道把这三节整段倒序,得到 1 , 2 , 3 1,2,3 1,2,3,耗电 0 0 0。
题解和思路
思路
实现思路:逻辑分析
- 重点分析出来下面这个规律
- 三节反转:不改变交换的奇偶性,利用三节反转可以使得奇数位置数任意排列,偶数位置数任意排列
- 两节反转:改变奇偶。
- 因为每个奇数位置都可以通过相邻的奇数位置逐步交换,每个偶数位置也一样。因此,只要每个元素最终进入了正确的奇偶位置,剩下的排序就全部可以免费完成。
- 因此只需要统计原序列和正确位置序列,对应数奇偶错位数量
cnt即可。即可得出需要使用的两节反转数量,一次两节反转可以一奇一偶恢复到正确奇偶,所以结果为cnt /2 - 算法总体时间复杂度为
O(LlogL)
C++
cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int Q;
cin >> Q;
while (Q--) {
int L;
cin >> L;
vector<int> B(L), sortedB;
for (int i = 0; i < L; i++) {
cin >> B[i];
}
sortedB = B;
sort(sortedB.begin(), sortedB.end());
unordered_map<int, int> valuePos;
for (int i = 0; i < L; i++) {
valuePos[sortedB[i]] = i;
}
int cnt = 0;
for (int i = 0; i < L; i++) {
if ((i %2) != (valuePos[B[i]]) % 2) {
cnt++;
}
}
cout << cnt / 2 << '\n';
}
return 0;
}
Java
java
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int Q = sc.nextInt();
while (Q-- > 0) {
int L = sc.nextInt();
int[] B = new int[L];
int[] sortedB = new int[L];
for (int i = 0; i < L; i++) {
B[i] = sc.nextInt();
}
// 排序,得到每个元素的目标位置
sortedB = B.clone();
Arrays.sort(sortedB);
// 记录每个元素在排序后的位置
HashMap<Integer, Integer> valuePos = new HashMap<>();
for (int i = 0; i < L; i++) {
valuePos.put(sortedB[i], i);
}
int cnt = 0;
for (int i = 0; i < L; i++) {
if ((i % 2) != (valuePos.get(B[i]) % 2)) {
cnt++;
}
}
System.out.println(cnt / 2);
}
sc.close();
}
}
python
python
Q = int(input())
for _ in range(Q):
seq = list(map(int, input().split()))
L = seq[0]
B = seq[1:]
# 排序,得到每个元素的目标位置
sortedB = sorted(B)
# 记录每个元素在排序后的位置
valuePos = {}
for i in range(L):
valuePos[sortedB[i]] = i
cnt = 0
for i in range(L):
if i % 2 != valuePos[B[i]] % 2:
cnt += 1
print(cnt // 2)
Go
go
package main
import (
"bufio"
"fmt"
"os"
"sort"
)
func main() {
reader := bufio.NewReader(os.Stdin)
writer := bufio.NewWriter(os.Stdout)
defer writer.Flush()
var Q int
fmt.Fscan(reader, &Q)
for ; Q > 0; Q-- {
var L int
fmt.Fscan(reader, &L)
B := make([]int, L)
sortedB := make([]int, L)
for i := 0; i < L; i++ {
fmt.Fscan(reader, &B[i])
sortedB[i] = B[i]
}
// 排序,得到每个元素的目标位置
sort.Ints(sortedB)
// 记录每个元素在排序后的位置
valuePos := make(map[int]int)
for i := 0; i < L; i++ {
valuePos[sortedB[i]] = i
}
cnt := 0
for i := 0; i < L; i++ {
if i%2 != valuePos[B[i]]%2 {
cnt++
}
}
fmt.Fprintln(writer, cnt/2)
}
}
Javascript
js
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
let input = [];
rl.on('line', line => {
input.push(line.trim());
});
rl.on('close', () => {
let idx = 0;
const Q = Number(input[idx++]);
const ans = [];
for (let q = 0; q < Q; q++) {
const seq = input[idx++].split(/\s+/).map(Number);
const L = seq[0];
const B = seq.slice(1);
// 排序,得到每个元素的目标位置
const sortedB = [...B].sort((a, b) => a - b);
// 记录每个元素在排序后的位置
const valuePos = new Map();
for (let i = 0; i < L; i++) {
valuePos.set(sortedB[i], i);
}
let cnt = 0;
for (let i = 0; i < L; i++) {
if (i % 2 !== valuePos.get(B[i]) % 2) {
cnt++;
}
}
ans.push(String(Math.floor(cnt / 2)));
}
console.log(ans.join('\n'));
});