8.25第二题训练

A10 度假酒店 题解复盘

模块:前缀和思想 + 预处理

类型:区间排除查询 / 左右最大值维护

目标:每天有一个不可用区间 L,R,求剩余房间中人数最大的房间容量。


基本信息

项目 内容
题目编号、来源 A10 - 度假酒店
训练层级 A基础算法 / 区间查询
知识版块 前缀最大值、后缀最大值、预处理
核心模型 多次询问区间删除后的最大值查询

解题前・关键信号识别

维度 分析
目标、约束、底层结构 有 N 个房间,每天给出一个不可使用区间 L,R,需要找到剩余房间中的最大容量。核心是:查询一个数组去掉中间一段后的最大值。
数据规模 N≤100000,D≤100000。如果每次查询都遍历剩余房间,复杂度 O(ND),会超时。需要预处理。
候选算法和依据 ① 暴力枚举剩余房间:O(ND),不可行。 ② 预处理左侧最大值和右侧最大值:正确。因为删除 L,R 后,只可能来自两个区域:1~L-1 或 R+1~N。
复杂度预判 预处理:O(N) 每次询问:O(1) 总复杂度:O(N+D)

解题后・外化复盘

维度 内容
实现结构 / 核心思路 ① 提前计算每个位置左侧最大房间容量。 ② 提前计算每个位置右侧最大房间容量。 ③ 查询 L,R 被删除后,只需要比较: 左边:pre[L-1] 右边:suf[R+1] 答案: cpp<br>max(pre[L-1],suf[R+1])<br>
错因回溯 这题容易想到每次删除区间后重新扫描剩余房间,但由于 D 很大,会导致超时。关键是发现查询结构固定,可以提前维护信息。
边界和易错点 1. 左边范围是 1~L-1,所以使用 pre[L-1]。 2. 右边范围是 R+1~N,所以使用 suf[R+1]。 3. 后缀数组需要开到 n+2,否则访问 suf[R+1] 时可能越界。 4. 当删除中间区间时,不需要考虑 L,R 内的数据。
下次看到什么信号,我应该想到这个方法 看到: ① 多次询问数组区间变化后的最大/最小值 ② 每次删除一个连续区间 ③ 查询剩余部分的信息 想到:预处理前缀 + 后缀信息。

AC完整代码

复制代码
#include<iostream>
#include<algorithm>
using namespace std;

int main(){

    int n;
    cin>>n;

    int a[n+2];

    int pre[n+2]={0};
    int suf[n+2]={0};


    for(int i=1;i<=n;i++){

        cin>>a[i];

        pre[i]=max(pre[i-1],a[i]);
    }


    for(int i=n;i>=1;i--){

        suf[i]=max(suf[i+1],a[i]);
    }


    int d;
    cin>>d;


    while(d--){

        int l,r;

        cin>>l>>r;


        cout<<max(pre[l-1],suf[r+1])<<endl;

    }


    return 0;
}

CSP202412B 梦境巡查 题解复盘

模块:数学推导 + 前缀最大值 + 后缀最大值

类型:差分思想 / 区间最大值维护

目标:对于每个可能失效的补给点 i,求最少需要携带多少初始能量 wi,保证完整巡查。


基本信息

项目 内容
题目编号、来源 CSP202412B 梦境巡查
训练层级 CSP 第二题训练
知识版块 前缀和、后缀处理、数学建模
核心模型 将巡查过程转化为初始能量需要满足的一系列不等式,求最大缺口

解题前・关键信号识别

维度 分析
目标、约束、底层结构 巡查过程中,每经过一个区域都会消耗 a[i],并获得补给 b[i]。如果某个区域补给失效,需要增加初始能量。目标是求每个 i 失效时的最小初始能量。
数据规模 n≤10⁵。如果每次模拟一次巡查,需要 O(n²),无法通过。需要预处理。
候选算法和依据 ① 暴力模拟每个失效点:O(n²),只能过小数据。 ② 将能量变化转化为前缀差值,求过程中最大亏空。 ③ 利用前缀最大值和后缀最大值快速回答每个 i。
复杂度预判 预处理 O(n),每个答案 O(1),总复杂度 O(n)。

解题后・外化复盘

维度 内容
实现结构 / 核心思路 ① 把初始能量看成需要抵消整个过程中的最大亏空。 ② 如果第 i 个补给失效,那么: 左边 1~i-1 按正常情况计算。 右边 i~n 少了 b[i] 补给。 ③ 所以答案: cpp<br>max(pre[i-1],suf[i]+b[i])<br>
错因回溯 容易直接模拟每个失效位置: 枚举 i,然后重新走一遍 n 个区域。 复杂度 O(n²),n=10⁵ 时无法通过。直接模拟有80分 关键是发现每个位置的答案都来自固定的前缀和后缀信息。(受上面那个题影响想到前缀和后缀)
边界和易错点 1. 区域编号从 1 开始,但是 a[0] 是出发消耗。 2. b[i] 只影响到 i 号区域之后。 3. 失效区域 i 的补给需要从后半部分答案中补回来,所以出现 +b[i]。 4. 使用 long long,避免累计能量超过 int。
下次看到什么信号,我应该想到这个方法 看到: ① 一个过程不断累积资源变化 ② 需要保证全过程不失败 ③ 每个位置询问一次最大缺口 想到:前缀累计量 + 最大亏空。

AC完整代码

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

using ll = long long;

ll a[100005];
ll b[100005];

ll pre[100005];
ll suf[100005];

ll d[100005];


int main(){

    ios::sync_with_stdio(false);
    cin.tie(nullptr);


    int n;
    cin>>n;


    for(int i=0;i<=n;i++){
        cin>>a[i];
    }


    for(int i=1;i<=n;i++){
        cin>>b[i];
    }


    ll suma=0;
    ll sumb=0;


    for(int i=0;i<=n;i++){

        suma+=a[i];

        if(i>=1)
            sumb+=b[i];

        d[i]=suma-sumb;
    }


    pre[0]=d[0];

    for(int i=1;i<=n;i++){

        pre[i]=max(pre[i-1],d[i]);

    }


    suf[n]=d[n];

    for(int i=n-1;i>=1;i--){

        suf[i]=max(suf[i+1],d[i]);

    }


    for(int i=1;i<=n;i++){

        ll ans=max(
            pre[i-1],
            suf[i]+b[i]
        );


        if(i>1)
            cout<<" ";

        cout<<ans;
    }


    return 0;
}
相关推荐
星星.7221 小时前
2026河南萌新联赛第六场(郑州大学)补题B、D、L、J、I
数据结构·c++·算法
witton1 小时前
xmake中将proto文件生成C/C++文件然后再编译链接进项目
c语言·c++·mingw·protobuf·xmake·protobuf-c·protoc-gen-c
牛油果子哥q1 小时前
C++异常处理万字详解:try-throw-catch机制、栈展开、标准异常体系、自定义异常、工程规范、内存泄漏避坑
开发语言·jvm·c++
艾莉丝努力练剑1 小时前
【AI大模型接入SDK】C++日志体系与spdlog封装的理论部分
开发语言·c++·ide·人工智能·学习·面试·trae
旖旎夜光2 小时前
LCR 173:在点名(二分查找) —— 题解
数据结构·c++·算法·leetcode·二分查找
Lazionr3 小时前
模板进阶:深入理解模板机制
c++·windows
豆沙沙包?10 小时前
C++~~~stack容器、queue容器、list容器(p45-P56)
c++·windows·list
Frank_refuel10 小时前
【C++八股】面向对象
开发语言·c++
h_a_o777oah11 小时前
【图论】Tarjan 缩点:解决有向图中环的问题
c++·算法·图论·acm·强连通分量·缩点·tarjan