OPPO笔试真题 - 最小信号功率(C++/Py/Java /Js/Go)

最小信号功率

OPPO技术岗 8月8号笔试 第二题

题目内容

一条笔直的通信线路沿线分布着 nnn 个终端,按顺序编号为 111 到 nnn。第 iii 个终端需要至少 rir_iri 的信号强度才能正常运作。

你计划在某个整数坐标 ccc(1≤c≤n1 \le c \le n1≤c≤n)处设置一座基站,并为其选定一个非负整数发射功率 PPP。信号在传输过程中会随距离衰减:位于 iii 的终端实际收到的信号强度为 P−∣i−c∣P - |i - c|P−∣i−c∣。为保证所有终端都满足需求,必须对每个 iii 都有 P−∣i−c∣≥riP - |i - c| \ge r_iP−∣i−c∣≥ri。

你可以自由选择基站的位置 ccc。请计算在最优选址下,所需的最小发射功率 PPP。

终端数量 nnn 不超过 200000,每个 rir_iri 满足 0≤ri≤1090 \le r_i \le 10^90≤ri≤109。

输入描述

第一行包含一个整数 nnn,表示终端数量。 第二行包含 nnn 个整数 r1,r2,...,rnr_1, r_2, \dots, r_nr1,r2,...,rn,表示每个终端的最低信号需求,相邻整数之间以一个空格分隔。

输出描述

输出一行一个非负整数,表示所需的最小发射功率。

样例1

输入

复制代码
3
1 2 3

输出

复制代码
3

说明

我们有 3 个终端,需求 r=1,2,3r = 1, 2, 3r=1,2,3。 计算 A=max⁡i(ri+i)=max⁡(1+1,2+2,3+3)=6A = \max_i(r_i + i) = \max(1+1, 2+2, 3+3) = 6A=maxi(ri+i)=max(1+1,2+2,3+3)=6, B=max⁡i(ri−i)=max⁡(1−1,2−2,3−3)=0B = \max_i(r_i - i) = \max(1-1, 2-2, 3-3) = 0B=maxi(ri−i)=max(1−1,2−2,3−3)=0。 最小功率 P=⌈A+B2⌉=⌈6+02⌉=3P = \lceil \frac{A+B}{2} \rceil = \lceil \frac{6+0}{2} \rceil = 3P=⌈2A+B⌉=⌈26+0⌉=3。 将基站设置在位置 c=3c = 3c=3,功率 P=3P = 3P=3: 终端 1 实际接收 3−∣1−3∣=1≥13 - |1-3| = 1 \ge 13−∣1−3∣=1≥1; 终端 2 接收 3−∣2−3∣=2≥23 - |2-3| = 2 \ge 23−∣2−3∣=2≥2; 终端 3 接收 3−∣3−3∣=3≥33 - |3-3| = 3 \ge 33−∣3−3∣=3≥3。 所有终端满足需求,因此最小功率为 3

样例2

输入

复制代码
1
0

输出

复制代码
0

说明

边界情况:只有 1 个终端,需求为 0。 计算 A=0+1=1A = 0+1=1A=0+1=1,B=0−1=−1B = 0-1=-1B=0−1=−1,P=⌈1+(−1)2⌉=0P = \lceil \frac{1+(-1)}{2} \rceil = 0P=⌈21+(−1)⌉=0。 最优选址 c=1c=1c=1,功率 0 即可满足需求。

样例3

输入

复制代码
5
0 5 2 4 1

输出

复制代码
6

说明

5 个终端,需求 0,5,2,4,10,5,2,4,10,5,2,4,1。 A=max⁡(0+1,5+2,2+3,4+4,1+5)=max⁡(1,7,5,8,6)=8A = \max(0+1, 5+2, 2+3, 4+4, 1+5) = \max(1,7,5,8,6) = 8A=max(0+1,5+2,2+3,4+4,1+5)=max(1,7,5,8,6)=8, B=max⁡(0−1,5−2,2−3,4−4,1−5)=max⁡(−1,3,−1,0,−4)=3B = \max(0-1,5-2,2-3,4-4,1-5) = \max(-1,3,-1,0,-4) = 3B=max(0−1,5−2,2−3,4−4,1−5)=max(−1,3,−1,0,−4)=3。 P=⌈8+32⌉=6P = \lceil \frac{8+3}{2} \rceil = 6P=⌈28+3⌉=6。 选择 c=2c=2c=2,验证: 终端 1 接收 6−1=5≥06-1=5 \ge 06−1=5≥0; 终端 2 接收 6−0=6≥56-0=6 \ge 56−0=6≥5; 终端 3 接收 6−1=5≥26-1=5 \ge 26−1=5≥2; 终端 4 接收 6−2=4≥46-2=4 \ge 46−2=4≥4; 终端 5 接收 6−3=3≥16-3=3 \ge 16−3=3≥1。 功率 6 可行,且是最小值。

思路

枚举

  1. 选取任意位置作为发射点,所需最小功率为max(左侧终端所需功率最大值, 右侧终端所需功率最大值,本身所需功率)
  2. 基于1的分析,可以预处理统计出每个位置(包含本身)左/右侧所需功率所需功率最大值。
  3. 然后枚举发射点,记录最小所需功率。
  4. 算法总体时间复杂为O(n)

C++

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n;
    cin >> n;
    vector<long> a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    
    // 左侧包含本身所需最小功率 右侧包含本身所需最小功率 
    vector<long> left(n), right(n);
    
    int leftMaxIndex = 0;
    for (int i = 0; i < n; i++) {
        long lMax = a[leftMaxIndex] + (i - leftMaxIndex);
        long cur = a[i];
        left[i] = max(lMax, cur);
        if (cur > lMax) {
            leftMaxIndex = i;
        }
    }

    int rightMaxIndex = n -1;
    for (int i = n - 1; i >= 0; i--) {
        long rMax = a[rightMaxIndex] + (rightMaxIndex - i);
        long cur = a[i];
        right[i] = max(rMax, cur);
        if (cur > rMax) {
            rightMaxIndex = i;
        }
    }
    long ans = LONG_MAX;
    for (int i = 0; i < n; i++) {
        ans = min(ans, max(left[i], right[i]));
    }
    cout << ans;
    return 0;
}

java

java 复制代码
import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();
        long[] a = new long[n];
        for (int i = 0; i < n; i++) {
            a[i] = sc.nextLong();
        }

        // 左侧包含本身所需最小功率 右侧包含本身所需最小功率
        long[] left = new long[n];
        long[] right = new long[n];

        int leftMaxIndex = 0;
        for (int i = 0; i < n; i++) {
            long lMax = a[leftMaxIndex] + (i - leftMaxIndex);
            long cur = a[i];
            left[i] = Math.max(lMax, cur);
            if (cur > lMax) {
                leftMaxIndex = i;
            }
        }

        int rightMaxIndex = n - 1;
        for (int i = n - 1; i >= 0; i--) {
            long rMax = a[rightMaxIndex] + (rightMaxIndex - i);
            long cur = a[i];
            right[i] = Math.max(rMax, cur);
            if (cur > rMax) {
                rightMaxIndex = i;
            }
        }

        long ans = Long.MAX_VALUE;
        for (int i = 0; i < n; i++) {
            ans = Math.min(ans, Math.max(left[i], right[i]));
        }

        System.out.println(ans);
    }
}

python

python 复制代码
n = int(input())
a = list(map(int, input().split()))

# 左侧包含本身所需最小功率 右侧包含本身所需最小功率
left = [0] * n
right = [0] * n

leftMaxIndex = 0
for i in range(n):
    lMax = a[leftMaxIndex] + (i - leftMaxIndex)
    cur = a[i]
    left[i] = max(lMax, cur)
    if cur > lMax:
        leftMaxIndex = i

rightMaxIndex = n - 1
for i in range(n - 1, -1, -1):
    rMax = a[rightMaxIndex] + (rightMaxIndex - i)
    cur = a[i]
    right[i] = max(rMax, cur)
    if cur > rMax:
        rightMaxIndex = i

ans = float('inf')
for i in range(n):
    ans = min(ans, max(left[i], right[i]))

print(ans)

javascript

js 复制代码
const readline = require('readline');

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

const input = [];

rl.on('line', line => {
    input.push(line.trim());
});

rl.on('close', () => {
    const n = Number(input[0]);
    const a = input[1].split(/\s+/).map(Number);

    // 左侧包含本身所需最小功率 右侧包含本身所需最小功率
    const left = new Array(n).fill(0);
    const right = new Array(n).fill(0);

    let leftMaxIndex = 0;
    for (let i = 0; i < n; i++) {
        const lMax = a[leftMaxIndex] + (i - leftMaxIndex);
        const cur = a[i];
        left[i] = Math.max(lMax, cur);
        if (cur > lMax) {
            leftMaxIndex = i;
        }
    }

    let rightMaxIndex = n - 1;
    for (let i = n - 1; i >= 0; i--) {
        const rMax = a[rightMaxIndex] + (rightMaxIndex - i);
        const cur = a[i];
        right[i] = Math.max(rMax, cur);
        if (cur > rMax) {
            rightMaxIndex = i;
        }
    }

    let ans = Number.MAX_SAFE_INTEGER;
    for (let i = 0; i < n; i++) {
        ans = Math.min(ans, Math.max(left[i], right[i]));
    }

    console.log(ans);
});

Go

go 复制代码
package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
)

func main() {
	in := bufio.NewReader(os.Stdin)

	var n int
	fmt.Fscan(in, &n)

	a := make([]int64, n)
	for i := 0; i < n; i++ {
		fmt.Fscan(in, &a[i])
	}

	// 左侧包含本身所需最小功率 右侧包含本身所需最小功率
	left := make([]int64, n)
	right := make([]int64, n)

	leftMaxIndex := 0
	for i := 0; i < n; i++ {
		lMax := a[leftMaxIndex] + int64(i-leftMaxIndex)
		cur := a[i]
		if lMax > cur {
			left[i] = lMax
		} else {
			left[i] = cur
		}
		if cur > lMax {
			leftMaxIndex = i
		}
	}

	rightMaxIndex := n - 1
	for i := n - 1; i >= 0; i-- {
		rMax := a[rightMaxIndex] + int64(rightMaxIndex-i)
		cur := a[i]
		if rMax > cur {
			right[i] = rMax
		} else {
			right[i] = cur
		}
		if cur > rMax {
			rightMaxIndex = i
		}
	}

	ans := int64(math.MaxInt64)
	for i := 0; i < n; i++ {
		cur := left[i]
		if right[i] > cur {
			cur = right[i]
		}
		if cur < ans {
			ans = cur
		}
	}

	fmt.Println(ans)
}
相关推荐
千里马学框架7 个月前
安卓aosp 16新特性分屏收藏保存功能AppPairIcon剖析
android·面试·framework·收藏·分屏·oppo·小米汽车
2013编程爱好者9 个月前
【OPPO】OPPO Reno 15系列详解
oppo·数码·coloros
yidiancaijing3 年前
折叠旗舰新战局:华为先行,OPPO接棒
oppo
唯之为之3 年前
OPPO主题组件开发 - 调试与预览
组件·主题·oppo