京东笔试 京东笔试题 0816

笔试时间:2025年8月16日

往年笔试合集:

2023春招秋招笔试合集

2024春招秋招笔试合集

第一题

你有一个长度为n的序列A: a₁,a₂,…,aₙ,你需要进行如下操作至多一次: 选择一个区间[L,R] (1≤L≤R≤n),将a_L,a_{L+1},…,a_R全部加1。即a_L,a_{L+1},…,a_R均变为a_L+1,a_{L+1}+1,…,a_R+1 设变化后的序列为B: b₁,b₂,…,bₙ,你需要最大化inv(A)-inv(B),其中inv()函数表示该序列的逆序对数量,即满足i<j,a_i>a_j的二元组(i,j)个数。换句话说,你需要尽可能地减小序列A的逆序对数量。

输入描述

第一行一个正整数T,表示数据组数; 对于每一组数据,第一行一个正整数n;

第二行n个正整数a₁,a₂,…,aₙ,表示序列A。 1≤n≤10⁵; 1≤T≤5; 1≤a_i≤n。

输出描述

对于每一组数据,输出一个整数,表示最大的inv(A)-inv(B)。

样例输入

3

5

4 2 3 1 5

5

1 2 3 4 5

3

2 1 1

样例输出

2

0

2

说明: 第一组数据,选择区间[3,4],变化后的序列为[4 2 4 2 5],逆序对数量为3;变化前逆序对数量为5。 第二组数据,选择任意区间都不会减小逆序对数量。 第三组数据,选择区间[2,3],变化后的序列为[2 2 2],逆序对数量为0;变化前逆序对数量为2。

参考题解

我们只在一个连续区间把所有数都加 1。对位置 i 的值 v 来说,这个操作只影响两种配对: (1) 右边等于 v−1 的元素会让原本的逆序对消失(赚到的收益 = 右侧 v−1 的个数); (2) 左边等于 v+1 的元素会新产生逆序对(损失 = 左侧 v+1 的个数)。 所以位置 i 的净收益 = 右侧(v−1)数量 − 左侧(v+1)数量。预处理每个取值的全局出现次数 totalCount[·],边扫边维护左侧计数 seenPrefix[·],就能在 O(1) 得到当前位置的增量,把这些增量累加得到把区间一直向右扩的总收益,遍历过程中取到的最大值就是答案。时间复杂度 O(n),空间 O(n)。

C++:

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int T;
    if (!(cin >> T)) return 0;
    while (T--) {
        int n;
        cin >> n;
        vector<int> arr(n);
        for (int i = 0; i < n; ++i) cin >> arr[i];

        vector<int> totalCount(n + 2, 0);
        for (int v : arr) ++totalCount[v];

        vector<int> seenPrefix(n + 3, 0);
        long long currentGain = 0;
        long long bestGain = 0;

        for (int i = 0; i < n; ++i) {
            bestGain = max(bestGain, currentGain);
            int v = arr[i];
            currentGain += (long long)totalCount[v - 1] - seenPrefix[v - 1] - seenPrefix[v + 1];
            ++seenPrefix[v];
        }
        bestGain = max(bestGain, currentGain);

        cout << bestGain << "\n";
    }
    return 0;
}

Java:

import java.io.*;
import java.util.*;

public class Main {
    // 快速读入
    private static final class FastScanner {
        private final InputStream in;
        private final byte[] buffer = new byte[1 << 16];
        private int ptr = 0, len = 0;

        FastScanner(InputStream is) { this.in = is; }

        private int read() throws IOException {
            if (ptr >= len) {
                len = in.read(buffer);
                ptr = 0;
                if (len <= 0) return -1;
            }
            return buffer[ptr++];
        }

        int nextInt() throws IOException {
            int c, sgn = 1, x = 0;
            do { c = read(); } while (c <= 32 && c != -1);
            if (c == '-') { sgn = -1; c = read(); }
            while (c > 32 && c != -1) {
                x = x * 10 + (c - '0');
                c = read();
            }
            return x * sgn;
        }
    }

    public static void main(String[] args) throws Exception {
        FastScanner fs = new FastScanner(System.in);
        StringBuilder out = new StringBuilder();

        int T;
        try { T = fs.nextInt(); } catch (Exception e) { return; }
        for (int _t = 0; _t < T; _t++) {
            int n = fs.nextInt();
            int[] arr = new int[n];
            for (int i = 0; i < n; i++) arr[i] = fs.nextInt();

            int[] totalCount = new int[n + 2];
            for (int v : arr) ++totalCount[v];

            int[] seenPrefix = new int[n + 3];
            long currentGain = 0L;
            long bestGain = 0L;

            for (int i = 0; i < n; i++) {
                if (currentGain > bestGain) bestGain = currentGain;
                int v = arr[i];
                currentGain += (long) totalCount[v - 1] - seenPrefix[v - 1] - seenPrefix[v + 1];
                ++seenPrefix[v];
            }
            if (currentGain > bestGain) bestGain = currentGain;

            out.append(bestGain).append('\n');
        }

        System.out.print(out.toString());
    }
}

Python:

import sys

def main():
    data = list(map(int, sys.stdin.buffer.read().split()))
    it = iter(data)
    try:
        T = next(it)
    except StopIteration:
        return

    out_lines = []
    for _ in range(T):
        n = next(it)
        arr = [next(it) for _ in range(n)]

        total = [0] * (n + 2)
        for v in arr:
            total[v] += 1

        seen = [0] * (n + 3)
        current = 0
        best = 0

        for v in arr:
            if current > best:
                best = current
            current += total[v - 1] - seen[v - 1] - seen[v + 1]
            seen[v] += 1

        if current > best:
            best = current

        out_lines.append(str(best))

    sys.stdout.write("\n".join(out_lines))

if __name__ == "__main__":
    main()

第二题

在一场跳水比赛中,共有n位裁判依次为选手打分(打分为非负整数)。根据比赛规则,需要从所有裁判的打分中,选取连续的m个打分来计算选手的

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

2025 春招笔试合集 文章被收录于专栏

2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南

全部评论

相关推荐

评论
点赞
1
分享

创作者周榜

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