【秋招笔试】2025.08.10米哈游秋招机考真题改编

✅ 秋招备战指南 ✅

💡 学习建议:

  • 先尝试独立解题
  • 对照解析查漏补缺

🧸 题面描述背景等均已深度改编,做法和题目本质基本保持一致。

🍹 感谢各位朋友们的订阅,你们的支持是我们创作的最大动力

🌸 目前本专栏已经上线110+套真题改编解析,后续会持续更新的

春秋招笔试机考招合集 -> 互联网必备刷题宝典🔗

题目一:图书馆整理计划

1️⃣:贪心策略从左到右固定每个位置的最优元素

2️⃣:使用线段树维护区间最小值信息,支持单点更新和区间查询

3️⃣:每次选择后缀中的最小值交换到当前位置

难度:中等

这道题目的核心是贪心思想,通过每次将后缀区间的最小值移动到当前位置来保证字典序最小。线段树的使用使得我们能够高效地进行区间最值查询和单点更新,时间复杂度为 O(n log n)。

题目二:花园景观设计

1️⃣:将圆环问题转化为线性问题,通过数组扩展处理

2️⃣:利用前缀和技巧计算正向和反向建造成本

3️⃣:数学推导得出反向成本公式,避免重复计算

难度:中等

这道题目巧妙地结合了圆环数据结构和前缀和优化。关键insight是发现反向建造成本可以通过数学公式快速计算,避免了枚举所有建造顺序的复杂度。

题目三:学生影响力评估

1️⃣:通过代数变换简化影响关系条件

2️⃣:将问题转化为区间最大值及其出现次数的查询

3️⃣:使用线段树维护区间最值信息

难度:中等偏难

这道题目需要深入理解影响关系的数学本质,通过转换将复杂的图论问题简化为区间查询问题。线段树的应用使得我们能够高效地处理多次查询,实现 O((n+q) log n) 的时间复杂度。

01. 图书馆整理计划

问题描述

小兰是图书馆的管理员,她面临着一个棘手的图书整理任务。图书馆的一个书架上有 本书,这些书的编号恰好是 的一个排列,但由于读者的随意摆放,书籍的顺序变得杂乱无章。

小兰希望将这些书按照编号从小到大的顺序重新排列,但由于时间限制,她最多只能进行 次交换操作。每次操作可以选择任意两本书进行位置交换。

现在小兰想知道,在有限的交换次数内,她能够得到的字典序最小的书籍排列是什么?

输入格式

每个测试文件均包含多组测试数据。

第一行包含一个正整数 (),表示测试数据的组数。

对于每组测试数据:

第一行包含两个正整数 (, ),分别表示书籍的数量和最多可以进行的交换次数。

第二行包含 个正整数 (),表示当前书架上书籍的编号排列,保证是 的一个排列。

保证所有测试数据中 的总和不超过

输出格式

对于每组测试数据,输出一行 个整数,表示经过至多 次交换操作后能够得到的字典序最小的排列。

样例输入

2
2 1
2 1
3 4
3 2 1

样例输出

1 2
1 2 3
样例 解释说明
样例1 可以交换位置1和位置2的书籍,将排列 [2,1] 变为 [1,2]
样例2 可以交换位置1和位置3的书籍,将排列 [3,2,1] 变为 [1,2,3]

数据范围

  • 保证所有测试数据中 的总和不超过

题解

这道题的核心思想是贪心策略。每次交换操作可以将后缀区间中的任意元素移动到当前位置,所以为了得到字典序最小的排列,应该从左到右依次固定每个位置上的最优元素。

具体做法是:从左到右遍历每个位置,如果当前位置右侧(包括当前位置)存在更小的元素,就将最小的那个元素交换到当前位置。这样可以保证每一步都让排列在字典序意义下变得更优。

为了高效地找到区间中的最小值及其位置,可以使用线段树来维护区间最小值信息。线段树支持单点更新和区间查询,时间复杂度为

总的时间复杂度为 ,对于给定的数据范围完全可以接受。

参考代码

  • Python
import sys
input = lambda: sys.stdin.readline().strip()

class SegTree:
    def __init__(self, arr):
        self.n = len(arr)
        self.tree = [(0, 0)] * (4 * self.n)  # (value, index)
        self.build(1, 0, self.n - 1, arr)
    
    def build(self, node, l, r, arr):
        if l == r:
            self.tree[node] = (arr[l], l)
            return
        mid = (l + r) // 2
        self.build(2 * node, l, mid, arr)
        self.build(2 * node + 1, mid + 1, r, arr)
        # 合并左右子树的结果,选择值更小的,如果值相等则选择下标更小的
        left_val, left_idx = self.tree[2 * node]
        right_val, right_idx = self.tree[2 * node + 1]
        if left_val < right_val or (left_val == right_val and left_idx < right_idx):
            self.tree[node] = (left_val, left_idx)
        else:
            self.tree[node] = (right_val, right_idx)
    
    def query(self, node, l, r, ql, qr):
        if ql <= l and r <= qr:
            return self.tree[node]
        mid = (l + r) // 2
        res_val, res_idx = float('inf'), float('inf')
        
        if ql <= mid:
            val, idx = self.query(2 * node, l, mid, ql, qr)
            if val < res_val or (val == res_val and idx < res_idx):
                res_val, res_idx = val, idx
        if qr > mid:
            val, idx = self.query(2 * node + 1, mid + 1, r, ql, qr)
            if val < res_val or (val == res_val and idx < res_idx):
                res_val, res_idx = val, idx
        
        return res_val, res_idx
    
    def update(self, node, l, r, pos, val):
        if l == r:
            self.tree[node] = (val, pos)
            return
        mid = (l + r) // 2
        if pos <= mid:
            self.update(2 * node, l, mid, pos, val)
        else:
            self.update(2 * node + 1, mid + 1, r, pos, val)
        
        # 更新当前节点
        left_val, left_idx = self.tree[2 * node]
        right_val, right_idx = self.tree[2 * node + 1]
        if left_val < right_val or (left_val == right_val and left_idx < right_idx):
            self.tree[node] = (left_val, left_idx)
        else:
            self.tree[node] = (right_val, right_idx)

def solve():
    n, m = map(int, input().split())
    books = list(map(int, input().split()))
    
    # 构建线段树
    seg = SegTree(books)
    
    # 贪心地从左到右固定每个位置
    for i in range(n):
        if m == 0:
            break
        
        # 查找从位置i到末尾的最小值
        min_val, min_pos = seg.query(1, 0, n - 1, i, n - 1)
        
        # 如果当前位置不是最小值,则进行交换
        if min_val < books[i]:
            books[i], books[min_pos] = books[min_pos], books[i]
            # 更新线段树
            seg.update(1, 0, n - 1, i, books[i])
            seg.update(1, 0, n - 1, min_pos, books[min_pos])
            m -= 1
    
    return ' '.join(map(str, books))

T = int(input())
for _ in range(T):
    print(solve())
  • Cpp
#include <bits/stdc++.h>
using namespace std;

struct SegNode {
    int val, idx;
    SegNode(int v = INT_MAX, int i = INT_MAX) : val(v), idx(i) {}
    bool operator<(const SegNode& other) const {
        return val < other.val || (val == other.val && idx < other.idx);
    }
};

class SegTree {
private:
    int sz;
    vector<SegNode> tree;
    
    void build(int v, int tl, int tr, const vector<int>& arr) {
        if (tl == tr) {
            tree[v] = SegNode(arr[tl], tl);
        } else {
            int tm = (tl + tr) / 2;
            build(2*v, tl, tm, arr);
            build(2*v+1, tm+1, tr, arr);
            tree[v] = min(tree[2*v], tree[2*v+1]);
        }
    }
    
    void update(int v, int tl, int tr, int pos, int val) {
        if (tl == tr) {
            tree[v] = SegNode(val, pos);
        } else {
            int tm = (tl + tr) / 2;
            if (pos <= tm)
                update(2*v, tl, tm, pos, val);
            else
                update(2*v+1, tm+1, tr, pos, val);
            tree[v] = min(tree[2*v], tree[2*v+1]);
        }
    }
    
    SegNode query(int v, int tl, int tr, int l, int r) {
        if (l > r) return SegNode();
        if (l == tl && r == tr) return tree[v];
        int tm = (tl + tr) / 2;
        return min(query(2*v, tl, tm, l, min(r, tm)),
                   query(2*v+1, tm+1, tr, max(l, tm+1), r));
    }
    
public:
    SegTree(const vector<int>& arr) : sz(arr.size()) {
        tree.resize(4 * sz);
        build(1, 0, sz-1, arr);
    }
    
    void update(int pos, int val) {
        update(1, 0, sz-1, pos, val);
    }
    
    SegNode query(int l, int r) {
        return query(1, 0, sz-1, l, r);
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int t;
    cin >> t;
    
    while (t--) {
        int n, m;
        cin >> n >> m;
        
        vector<int> books(n);
        for (int i = 0; i < n; i++) {
            cin >> books[i];
        }
        
        SegTree seg(books);
        
        // 贪心地从左到右处理每个位置
        for (int i = 0; i < n && m > 0; i++) {
            SegNode min_node = seg.query(i, n-1);
            
            // 如果找到的最小值比当前位置的值小,进行交换
            if (min_node.val < books[i]) {
                swap(books[i], books[min_node.idx]);
                seg.update(i, books[i]);
                seg.update(min_node.idx, books[min_node.idx]);
                m--;
            }
        }
        
        // 输出结果
        for (int i = 0; i < n; i++) {
            if (i > 0) cout << " ";
            cout << books[i];
        }
        cout << "\n";
    }
    
    return 0;
}
  • Java
import java.io.*;
import java.util.*;

public class Main {
    static class SegNode {
        int val, idx;
        
        SegNode(int val, int idx) {
            this.val = val;
            this.idx = idx;
        }
        
        boolean isLess(SegNode other) {
            return val < other.val || (val == other.val && idx < other.idx);
        }
    }
    
    static class SegTree {
        private int size;
        private SegNode[] tree;
        
        SegTree(int[] arr) {
            size = arr.length;
            tree = new SegNode[4 * size];
            build(1, 0, size - 1, arr);
        }
        
        private void build(int v, int tl, int tr, int[] arr) {
            if (tl == tr) {
                tree[v] = new SegNode(arr[tl], tl);
            } else {
                int tm = (tl + tr) / 2;
                build(2 * v, tl, tm, arr);
                build(2 * v + 1, tm + 1, tr, arr);
                tree[v] = min(tree[2 * v], tree[2 * v + 1]);
            }
        }
        
        void update(int pos, int val) {
            update(1, 0, size - 1, pos, val);
        }
        
        private void update(int v, int tl, int tr, int pos, int val) {
            if (tl == tr) {
                tree[v] = new SegNode(val, pos);
            } else {
                int tm = (tl + tr) / 2;
                if (pos <= tm) {
                    update(2 * v, tl, tm, pos, val);
                } else {
                    update(2 * v + 1, tm + 1, tr, pos, val);
                }
                tree[v] = min(tree[2 * v], tree[2 * v + 1]);
            }
        }
        
        SegNode query(int l, int r) {
            return query(1, 0, size - 1, l, r);
        }
        
        private SegNode query(int v, int tl, int tr, int l, int r) {
            if (l > r) return new SegNode(Integer.MAX_VALUE, Integer.MAX_VALUE);
            if (l == tl && r == tr) return tree[v];
            int tm = (tl + tr) / 2;
            return min(query(2 * v, tl, tm, l, Math.min(r, tm)),
                      query(2 * v + 1, tm + 1, tr, Math.max(l, tm + 1), r));
        }
        
        private SegNode min(SegNode a, SegNode b) {
            return a.isLess(b) ? a : b;
        }
    }
    
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        PrintWrit

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

互联网刷题笔试宝典 文章被收录于专栏

互联网刷题笔试宝典,这里涵盖了市面上大部分的笔试题合集,希望助大家春秋招一臂之力

全部评论

相关推荐

08-11 12:12
门头沟学院 Java
点赞 评论 收藏
分享
评论
2
5
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务