【笔试刷题】网易-2026.03.08-改编真题
✅ 春招备战指南 ✅
💡 学习建议:
- 先尝试独立解题
- 对照解析查漏补缺
🧸 题面描述背景等均已深度改编,做法和题目本质基本保持一致。
🍹 感谢各位朋友们的订阅,你们的支持是我们创作的最大动力
🌸 目前本专栏已经上线200+套真题改编解析,后续会持续更新的
春秋招笔试机考招合集 -> 互联网必备刷题宝典🔗
网易-2026.03.08
这套网易题虽然只有两道,但都不是照着样子硬模拟就能稳过的类型。第一题要先分清“人走了多远”和“灯杖动了多远”不是一回事;第二题则要把“整次滚动”当成一条边,而不是把每个路过格子都拿来做决策点。
题目一:巡夜灯杖交接
这题最容易错在空队取杖阶段。最近的人只是先走过去接杖,那一段灯杖本身并没有移动,不能误算进贡献;把这个边界理顺后,整题就是按事件顺序做一次队列模拟。
难度:Mid
题目二:镜厅滚动寻路
真正的关键不是普通 BFS,而是先认清“只有静止时才能选方向”。把单次滚动预处理成“成功 / 停下 / 死循环”之后,再在静止点上做 BFS,结构就会一下子清楚很多。
难度:High
巡夜灯杖交接
问题描述
夜巡队要沿着一条笔直的长廊巡逻。
一共有 名巡逻员,第
名巡逻员最初站在位置
,自己的终点是位置
,满足
。所有人的起点两两不同,并且输入时已经按位置从小到大排好,也就是
。
一开始,只有第 名巡逻员拿着灯杖,并从位置
出发。
接下来会发生如下过程:
-
当当前拿灯杖的人经过某位尚未加入队伍的巡逻员起点时,这名巡逻员会立刻加入队尾。
-
当某名巡逻员到达自己的终点
时,他会立刻离队,并且之后不会再次加入队伍。
-
如果离队的人正好拿着灯杖,那么:
- 若此时队伍不为空,灯杖交给新的队首。
- 若此时队伍为空,灯杖会停在当前位置不动。此后,所有尚未加入过队伍的人中,起点离当前灯杖位置最近的那个人会先走到这里拿起灯杖,再继续前往自己的终点;如果他在去拿灯杖的路上经过了其他尚未加入过队伍的人的起点,这些人也会按经过顺序加入队尾。
题目保证最近的人总是唯一确定的。
定义第 名巡逻员的贡献值为:他拿着灯杖时,灯杖实际移动的总距离。请输出所有人的贡献值。
输入格式
第一行输入一个整数 ,表示巡逻员人数。
接下来 行,每行输入两个整数
,表示第
名巡逻员的起点和终点。
输出格式
输出一行 个整数,第
个整数表示第
名巡逻员的贡献值。
样例输入
4
1 10
5 6
9 30
20 25
样例输出
9 0 20 0
数据范围
| 样例 | 解释说明 |
|---|---|
| 样例 1 | 第 |
题解
这题看起来像很多人来回交接,真正要抓住的只有两件事:
- 灯杖的位置只会在“当前持有者继续向自己的终点前进”时发生变化。
- 一旦某个人接手时,发现自己的终点已经不在当前位置右边,那么他会立刻离队,贡献是
。
所以可以直接做事件模拟。
先维护下面几样状态:
u:当前灯杖所在位置。h:当前拿灯杖的人编号,如果现在没人拿,就记成-1。- 一个队列,表示已经加入但还没拿到灯杖的人。
joined[i]:第个人是否已经加入过队伍。
当 h != -1 时,当前持有者只会面临两个下一事件:
- 先经过某个还没加入的人的起点。
- 先到达自己的终点。
因为起点有序,可以直接在线性扫描里找出当前位置右边最近的未加入起点。然后比较这个起点和当前持有者终点,谁更靠左,谁就是下一事件:
- 如果先经过起点,那么灯杖移动到那个位置,这一段距离计入当前持有者贡献,新人入队。
- 如果先到达终点,那么灯杖移动到终点,这一段距离同样计入当前持有者贡献,然后当前持有者离队,把灯杖交给下一位。
- 如果二者恰好在同一位置,就先让新人加入,再让当前持有者离队。
当 h == -1 且队列也为空时,说明灯杖停住了。此时要从所有未加入的人里找出起点离 u 最近的人,让他走过来拿灯杖。
这里有一个容易误会的点:这个人是“先走到灯杖那里,再拿起灯杖继续前进”,所以他走过来这段路上,灯杖本身并没有移动,这一段距离不能算进贡献。
不过,他在路上经过的其他未加入起点,依然会按经过顺序入队。这个顺序只和他从自己的起点走向 u 的方向有关:
- 如果是从左往右走,就按起点从小到大入队。
- 如果是从右往左走,就按起点从大到小入队。
等他走到 u 之后,再把他设成新的持有者,继续模拟即可。
为什么这样做不会漏情况?
- 题目里的所有变化,本质上只有“某人加入”和“某人离队”这两类事件。
- 每次只需要处理最靠前的那个事件,处理后系统状态就会更新成下一段完全一样的问题。
- 队列顺序严格由题意给定,任何时候都不需要回退,所以整个过程可以顺着时间一直推下去。
复杂度方面,人数只有 。每次找下一事件、找最近未加入的人,最多都是扫一遍所有人。总事件数也是
级别,因此总时间复杂度是
,空间复杂度是
,完全够用。
参考代码
Python
import sys
from collections import deque
input = lambda: sys.stdin.readline().strip()
def solve() -> None:
n = int(input())
p = [0] * n
q = [0] * n
for i in range(n):
p[i], q[i] = map(int, input().split())
# joined[i] 表示第 i 个人是否已经加入过队伍。
joined = [False] * n
# ans[i] 记录第 i 个人持灯杖时,灯杖真正移动的总距离。
ans = [0] * n
que = deque()
# 初始时,第 0 个人已经加入并拿着灯杖。
joined[0] = True
h = 0
u = p[0]
left_cnt = 0
while left_cnt < n:
if h != -1:
# 如果当前持有者的终点已经在当前位置左边或重合,
# 那么他会立刻离队,灯杖不再移动。
if q[h] <= u:
left_cnt += 1
if que:
h = que.popleft()
else:
h = -1
continue
# 找到当前位置右边最近的未加入起点。
nxt_pos = None
nxt_id = -1
for i in range(n):
if not joined[i] and p[i] > u:
if nxt_pos is None or p[i] < nxt_pos:
nxt_pos = p[i]
nxt_id = i
leave_pos = q[h]
if nxt_pos is not None and nxt_pos < leave_pos:
# 先经过新人的起点。
ans[h] += nxt_pos - u
u = nxt_pos
joined[nxt_id] = True
que.append(nxt_id)
elif nxt_pos is not None and nxt_pos == leave_pos:
# 同一位置同时发生“新人加入”和“当前持有者离队”,
# 题意要求先加入,再交接。
ans[h] += nxt_pos - u
u = nxt_pos
joined[nxt_id] = True
que.append(nxt_id)
left_cnt += 1
if que:
h = que.popleft()
else:
h = -1
else:
# 先到达当前持有者的终点。
ans[h] += leave_pos - u
u = leave_pos
left_cnt += 1
if que:
h = que.popleft()
else:
h = -1
else:
# 现在没人拿灯杖,需要找最近的未加入者去把灯杖接起来。
best_dis = None
ni = -1
for i in range(n):
if not joined[i]:
d = abs(p[i] - u)
if best_dis is None or d < best_dis:
best_dis = d
ni = i
# 他是从 p[ni] 走到 u,中途经过的人会按经过顺序入队。
tmp = []
lo = min(p[ni], u)
hi = max(p[ni], u)
for i in range(n):
if not joined[i] and i != ni and lo < p[i] < hi:
tmp.append(i)
# 如果是从左往右走,经过顺序就是起点递增;
# 如果是从右往左走,经过顺序就是起点递减。
if p[ni] < u:
tmp.sort(key=lambda x: p[x])
else:
tmp.sort(key=lambda x: p[x], reverse=True)
for i in tmp:
joined[i] = True
que.append(i)
# 注意:这个人走到灯杖处之前,灯杖没有移动,
# 所以这里不能把 abs(p[ni] - u) 加进贡献。
joined[ni] = True
h = ni
print(*ans)
if __name__ == "__main__":
solve()
Cpp
#include <deque>
#include <iostream>
#include <vector>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<long long> p(n), q(n);
for (int i = 0; i < n; ++i) {
cin >> p[i] >> q[i];
}
// joined[i] 表示第 i 个人是否已经加入过队伍。
vector<int> joined(n, 0);
// ans[i] 统计第 i 个人真正让灯杖移动了多远。
vector<long long> ans(n, 0);
deque<int> que;
joined[0] = 1;
int h = 0;
long long u = p[0];
int leftCnt = 0;
while (leftCnt < n) {
if (h != -1) {
// 当前持有者的终点已经被越过时,会立刻离队。
if (q[h] <= u) {
++leftCnt;
if (!que.empty()) {
h = que.front();
que.pop_front();
} else {
h = -1;
}
continue;
}
// 在当前位置右边,找最近的未加入起点。
long long nxtPos = -1;
int nxtId = -1;
for (int i = 0; i < n; ++i) {
if (!joined[i] && p[i] > u) {
if (nxtPos == -1 || p[i] < nxtPos) {
nxtPos = p[i];
nxtId = i;
}
}
}
long long leavePos = q[h];
if (nxtId != -1 && nxtPos < leavePos) {
// 先路过新的起点,新人直接入队。
ans[h] += nxtPos - u;
u = nxtPos;
joined[nxtId] = 1;
que.push_back(nxtId);
} else if (nxtId != -1 && nxtPos == leavePos) {
// 同一点既有人加入,也有人离队,先加入再交接。
ans[h] += nxtPos - u;
u = nxtPos;
joined[nxtId] = 1;
que.push_back(nxtId);
++leftCnt;
if (!que.empty()) {
h = que.front();
que.pop_front();
} else {
h = -1;
}
} else {
// 先到终点,当前持有者离队。
ans[h] += leavePos - u;
u = leavePos;
++leftCnt;
if (!que.empty()) {
h = que.front();
que.pop_front();
} else {
h = -1;
}
}
} else {
// 灯杖停住时,找最近的未加入者来接。
long long bestDis = -1;
int ni = -1;
for (int i = 0; i < n; ++i) {
if (!joined[i]) {
long long d = p[i] > u ? p[i] - u : u - p[i];
if (bestDis == -1 || d < bestDis) {
bestDis = d;
ni = i;
}
}
}
vector<int> tmp;
long long lo = min(p[ni], u);
long long hi = max(p[ni], u);
for (int i = 0; i < n; ++i) {
if (!joined[i] && i != ni && lo < p[i] && p[i] < hi) {
tmp.push_back(i);
}
}
// 按“走去拿灯杖”的经过顺序入队。
if (p[ni] < u) {
for (int i = 0; i < (int)tmp.size(); ++i) {
for (int j = i + 1; j < (int)tmp.size(); ++j) {
if (p[tmp[i]] > p[tmp[j]]) {
swap(tmp[i], tmp[j]);
}
}
}
} else {
for (int i = 0; i < (int)tmp.size(); ++i) {
for (int j = i + 1; j < (int)tmp.size(); ++j) {
if (p[tmp[i]] < p[tmp[j]]) {
swap(tmp[i], tmp[j]);
}
}
}
}
for (int id : tmp) {
joined[id] = 1;
que.push_back(id);
}
// 走过来接灯杖这段,灯杖本身没动,不能计入贡献。
joined[ni] = 1;
h = ni;
}
}
for (int i = 0; i < n; ++i) {
if (i) {
cout << ' ';
}
cout << ans[i];
}
cout << '\n';
return 0;
}
Java
import java.io.BufferedInputStream;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class Main {
static class FastScanner {
private final BufferedInputStream in = new BufferedInputStream(System.in);
private final byte[] buf = new byte[1 << 16];
private int len = 0;
private int ptr = 0;
private int read() throws Exception {
if (ptr >= len) {
len = in.read(buf);
ptr = 0;
if (len <= 0) {
return -1;
}
}
return buf[ptr++];
}
long nextLong() throws Exception {
int c;
do {
c = read();
} while (c <= ' ' && c != -1);
long sign = 1;
if (c == '-') {
sign = -1;
c = read();
}
long val = 0;
while (c > ' ') {
val = val * 10 + c - '0';
c = read();
}
return val * sign;
}
}
public static void main(String[] args) throws Exception {
FastScanner fs = new FastScanner();
int n = (int) fs.nextLong();
long[] p = new long[n];
long[] q = new long[n];
for (int i = 0; i < n; ++i) {
p[i] = fs.nextLong();
q[i] = fs.nextLong();
}
boolean[] joined = new boolean[n];
long[] ans = new long[n];
ArrayDeque<Integer> que = new
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
互联网刷题笔试宝典,这里涵盖了市面上大部分的笔试题合集,希望助大家春秋招一臂之力