大厂真题 / 网易雷火

网易雷火 4.2 笔试真题 - 研发岗

本场考试概述

考试时间:2026年4月2日 考试岗位:研发岗 难度评级:中等偏难

考点分析

  1. 第一题:贪心(难度中等)
  2. 第二题:模拟(难度中等)
  3. 第三题:二分答案(难度困难)
  4. 第四题:模拟(难度困难)

建议策略

  1. 前两题贪心和模拟较为友好,务必拿满分
  2. 第三题二分答案是本场核心难点,需要理解 check 函数的构造方式
  3. 第四题系统模拟逻辑复杂,考场时间有限可优先保前三题

第一题:沙场点兵

题目描述

辽军派出 n 支小队,出战顺序固定。作为宋军指挥官,你手下也有 n 支小队,可自由排列。每轮双方各派一支小队对决,战力高者获胜(相同战力辽军获胜)。判断是否存在方案使我军胜场数严格过半。

样例

输入

2
5
2 5 7 1 6
3 5 6 2 7
3
3 3 3
3 3 3

输出

YES
NO

题解:贪心(田忌赛马)

将我军和辽军战力均升序排序。维护两个指针:hi 指向我方最强,lo 指向最弱;从对方最强开始逐个处理。若我方最强能赢对方最强,就匹配;否则用最弱的去消耗这场,保留强者对付后续。

时间复杂度:O(n log n)。 空间复杂度:O(n)。

import sys
input = sys.stdin.readline

def solve():
    n = int(input())
    a = list(map(int, input().split()))
    b = list(map(int, input().split()))
    a.sort()
    b.sort()
    win = 0
    lo = 0
    hi_a = n - 1
    hi_b = n - 1
    while hi_b >= lo:
        if a[hi_a] > b[hi_b]:
            win += 1
            hi_a -= 1
        else:
            lo += 1
        hi_b -= 1
    return "YES" if win > n // 2 else "NO"

T = int(input())
out = []
for _ in range(T):
    out.append(solve())
print("\n".join(out))

第二题:背包排序

题目描述

玩家有一个 n x m 的背包网格和 t 个物品。先按规则排序,然后按顺序逐个放入背包(优先行小、列小的位置)。物品属性包括 id、h x w(占用尺寸)、quality(品质)、type(种类)。排序规则:type 优先级(equip > weapon > item > other),品质高优先,id 小优先。输出能否放下所有物品及最终网格状态。

样例

输入

4 3 3
1 1 3 7 other
2 3 1 2 equip
3 2 2 4 other

输出

YES
2 3 3
2 3 3
2 0 0
1 1 1

题解:模拟

数据规模不大,直接模拟。排序后逐个放置,对每个物品遍历所有可能的左上角位置,找到第一个能放下的位置填入。

时间复杂度:O(t * n * m * h * w)。 空间复杂度:O(n * m)。

import sys
input = sys.stdin.readline

def type_order(s):
    return {"equip": 0, "weapon": 1, "item": 2, "other": 3}.get(s, 3)

def main():
    n, m, t = map(int, input().split())
    items = []
    for _ in range(t):
        parts = input().split()
        uid, h, w, q = int(parts[0]), int(parts[1]), int(parts[2]), int(parts[3])
        tp = parts[4]
        items.append((type_order(tp), -q, uid, h, w))
    items.sort()

    grid = [[0] * m for _ in range(n)]
    all_placed = True
    for _, _, uid, h, w in items:
        placed = False
        for r in range(n - h + 1):
            for c in range(m - w + 1):
                ok = all(grid[r + dr][c + dc] == 0 for dr in range(h) for dc in range(w))
                if ok:
                    for dr in range(h):
                        for dc in range(w):
                            grid[r + dr][c + dc] = uid
                    placed = True
                    break
            if placed:
                break
        if not placed:
            all_placed = False

    print("YES" if all_placed else "NO")
    for row in grid:
        print(" ".join(map(str, row)))

main()

第三题:不朽荣光

题目描述

索桥安全区域为 [0, L],桥上有 n 名敌人,坐标 x_i。每次射击选落点 p:命中 p 处的敌人直接淘汰,p 左侧敌人向左推 r 格,p 右侧敌人向右推 r 格。推出边界即淘汰。求最少射击次数。

样例

输入

3 10 2
3 5 9

输出

2

题解:二分答案

二分射击次数 k,判断 k 次是否足够。将敌人坐标排序后,前 a 个从左边界推下(需 x_i ≤ kr),中间 k 个直接命中,剩余从右边界推下(需 x_i ≥ L - kr)。用 upper_bound 找出满足左推条件的最大 a 值,检查右侧是否满足。

时间复杂度:O(n log n)。 空间复杂度:O(n)。

import sys
from bisect import bisect_right
input = sys.stdin.readline

def main():
    n, L, r = map(int, input().split())
    x = list(map(int, input().split()))
    x.sort()

    lo, hi = 0, n
    while lo < hi:
        mid = (lo + hi) // 2
        push_left = mid * r
        push_right = L - mid * r
        a = bisect_right(x, push_left)
        idx = a + mid
        if idx >= n or push_right <= 0 or x[idx] >= push_right:
            hi = mid
        else:
            lo = mid + 1
    print(lo)

main()

第四题:贴图流式加载

题目描述

实现一个带 LRU 回收机制的贴图流式加载系统。每张贴图有多级 mip,每级占用显存为上一级的 1/4。支持加载请求和主动清理信号,显存不足时按过期时间升序回收,输出所有状态变化日志。

样例

输入

120 4 7
1 3 0 20 1
1 2 0 40 2
1 1 0 40 2
1 4 0 20 1
5 4 0 20 1
6 4 0 20 1
99 -1

输出

1 3 0 20
1 2 0 70
1 1 0 120
6 1 -1 70
6 4 0 90
99 2 -1 40
99 3 -1 20
99 4 -1 0

题解:模拟

规模较小但规则复杂,用字典维护每个贴图的 mip 加载状态和过期时间,严格按规则执行。

时间复杂度:O(N * K * log K),其中 K 是活跃贴图数量。 空间复杂度:O(K * C)。

import sys
input = sys.stdin.readline

def mip_size(s, level):
    sz = s
    for _ in range(level):
        sz //= 4
    return sz

def main():
    M, D, N = map(int, input().split())
    props = {}
    mips_map = {}
    used_vram = 0
    result = []

    for _ in range(N):
        parts = input().split()
        t = int(parts[0])
        tid = int(parts[1])

        if tid == -1:
            to_remove = []
            for rid in sorted(mips_map.keys()):
                mips = mips_map[rid]
                expired = [m for m, exp in mips.items() if exp < t]
                if expired:
                    s, c = props[rid]
                    for m in expired:
                        used_vram -= mip_size(s, m)
                        del mips[m]
                    new_min = min(mips.keys()) if mips else -1
                    result.append(f"{t} {rid} {new_min} {used_vram}")
                    if not mips:
                        to_remove.append(rid)
            for rid in to_remove:
                del mips_map[rid]
                del props[rid]
        else:
            X = int(parts[2])
            s = int(parts[3])
            c = int(parts[4])
            props[tid] = (s, c)
            if tid not in mips_map:
                mips_map[tid] = {}
            mips = mips_map[tid]
            need_load = [m for m in range(X, c) if m not in mips]
            extra = sum(mip_size(s, m) for m in need_load)

            if extra > 0 and used_vram + extra > M:
                cands = []
                for rid, rmips in mips_map.items():
                    for m, exp in rmips.items():
                        if exp < t and not (rid == tid and m >= X):
                            cands.append((exp, rid, m))
                cands.sort()
                groups = {}
                for exp, rid, m in cands:
                    key = (exp, rid)
                    if key not in groups:
                        groups[key] = []
                    groups[key].append(m)
                for key in sorted(groups.keys()):
                    if used_vram + extra <= M:
                        break
                    exp, rid = key
                    rs, rc = props[rid]
                    rmips = mips_map[rid]
                    for m in groups[key]:
                        used_vram -= mip_size(rs, m)
                        del rmips[m]
                    new_min = min(rmips.keys()) if rmips else -1
                    result.append(f"{t} {rid} {new_min} {used_vram}")
                if used_vram + extra > M:
                    empty = [rid for rid, rmips in mips_map.items() if not rmips]
                    for rid in empty:
                        del mips_map[rid]
                        del props[rid]
                    continue

            if extra > 0:
                for m in need_load:
                    mips[m] = t + D
                    used_vram += mip_size(s, m)
            for m in list(mips.keys()):
                mips[m] = t + D
            if extra > 0:
                new_min = min(mips.keys())
                result.append(f"{t} {tid} {new_min} {used_vram}")
            empty = [rid for rid, rmips in mips_map.items() if not rmips]
            for rid in empty:
                del mips_map[rid]
                del props[rid]

    print("\n".join(result))

main()

小结

  • 第一题贪心(田忌赛马),将双方排序后双指针分配对局,O(n log n) 即可
  • 第二题模拟(背包排序),按多关键字排序后逐个放置矩形物品
  • 第三题二分答案是本场核心难点,关键在于将敌人分为左推、直接命中、右推三组
  • 第四题贴图流式加载规则复杂但数据规模不大,仔细处理 LRU 回收和日志输出即可