[R17A]谁在装弱

  • 难度 入门
  • 时限 1s
  • 空限 512m
  • 模拟

数据规模:1n1051 \le n \le 10^51bi1061 \le b_i \le 10^6,满分为 10610^6,且 bb 序列非递增。

思路

按题意,恰好一个同学装弱:把第 ii 名的真实分数 ai=bi+10a_i = b_i + 10,其余位置 aj=bja_j = b_j。装弱的人选 ii 合法,当且仅当替换后真实分数序列 aa 仍满足非递增,且每个 ai106a_i \le 10^6(满分约束)。

由于原 bb 序列已是非递增的,把第 ii 位从 bib_i 改成 bi+10b_i + 10(变大)只会破坏第 ii 位附近的相邻关系,远处不受影响。因此逐个枚举 ii,只需检查三个条件:

  1. 满分约束bi+10106b_i + 10 \le 10^6。例如样例 1 的第 1 名 b1=999991b_1 = 999991,真实分数 10000011000001 超过满分,不合法。
  2. 与左边的关系i>1i > 1):bi1bi+10b_{i-1} \ge b_i + 10。否则第 ii 名真实分数超过第 i1i-1 名,破坏降序。样例 1 的第 2 名 b1=999991<999992b_1 = 999991 < 999992 即不合法。
  3. 与右边的关系i<ni < n):bi+10bi+1b_i + 10 \ge b_{i+1}。否则第 i+1i+1 名反而更高,破坏降序。样例 1 的第 5 名 b4=10<b5+10=20b_4 = 10 < b_5 + 10 = 20 不合法。

三个条件都满足的 ii 即可能是装弱者,统计个数即可。

复杂度

时间 O(n)O(n),空间 O(n)O(n)

仓颉实现

import std.env.*
import std.convert.*

main(): Int64 {
    let reader = getStdIn()
    let n = Int64.parse(reader.readln().getOrThrow())
    let b = reader.readln().getOrThrow().split(" ", removeEmpty: true).map({ p: String => Int64.parse(p) })

    let FULL: Int64 = 1000000
    var ans: Int64 = 0
    for (i in 0..n) {
        let real = b[i] + 10
        if (real > FULL) {
            continue
        }
        // 检查替换后序列保持非递增 b[i-1] >= b[i](real 放在位置 i)
        var ok = true
        if (i > 0) {
            if (b[i - 1] < real) {
                ok = false
            }
        }
        if (ok && i < n - 1) {
            if (real < b[i + 1]) {
                ok = false
            }
        }
        if (ok) {
            ans += 1
        }
    }
    println(ans.toString())
    return 0
}