欢迎光临
我们一直在努力

csp信奥赛C++高频考点专项训练之前缀和&差分 --【一维差分】:海底高铁

csp信奥赛C++高频考点专项训练之前缀和&差分 –【一维差分】:海底高铁

在这里插入图片描述

题目描述

该铁路经过

N

N

N 个城市,每个城市都有一个站。不过,由于各个城市之间不能协调好,于是乘车每经过两个相邻的城市之间(方向不限),必须单独购买这一小段的车票。第

i

i

i 段铁路连接了城市

i

i

i 和城市

i

+

1

(

1

i

<

N

)

i+1(1\\leq i<N)

i+1(1i<N)。如果搭乘的比较远,需要购买多张车票。第

i

i

i 段铁路购买纸质单程票需要

A

i

A_i

Ai 博艾元。

虽然一些事情没有协调好,各段铁路公司也为了方便乘客,推出了 IC 卡。对于第

i

i

i 段铁路,需要花

C

i

C_i

Ci 博艾元的工本费购买一张 IC 卡,然后乘坐这段铁路一次就只要扣

B

i

(

B

i

<

A

i

)

B_i(B_i<A_i)

Bi(Bi<Ai) 元。IC 卡可以提前购买,有钱就可以从网上买得到,而不需要亲自去对应的城市购买。工本费不能退,也不能购买车票。每张卡都可以充值任意数额。对于第

i

i

i 段铁路的 IC 卡,无法乘坐别的铁路的车。

Uim 现在需要出差,要去

M

M

M 个城市,从城市

P

1

P_1

P1 出发分别按照

P

1

,

P

2

,

P

3

,


,

P

M

P_1,P_2,P_3,\\cdots,P_M

P1,P2,P3,,PM 的顺序访问各个城市,可能会多次访问一个城市,且相邻访问的城市位置不一定相邻,而且不会是同一个城市。

现在他希望知道,出差结束后,至少会花掉多少的钱,包括购买纸质车票、买卡和充值的总费用。

输入格式

第一行两个整数,

N

,

M

N,M

N,M

接下来一行,

M

M

M 个数字,表示

P

i

P_i

Pi

接下来

N

1

N-1

N1 行,表示第

i

i

i 段铁路的

A

i

,

B

i

,

C

i

A_i,B_i,C_i

Ai,Bi,Ci

输出格式

一个整数,表示最少花费。

输入输出样例 1
输入 1

9 10
3 1 4 1 5 9 2 6 5 3
200 100 50
300 299 100
500 200 500
345 234 123
100 50 100
600 100 1
450 400 80
2 1 10

输出 1

6394

说明/提示

2

2

2

3

3

3 以及

8

8

8

9

9

9 买票,其余买卡。

对于

30

%

30\\%

30% 数据

M

=

2

M=2

M=2

对于另外

30

%

30\\%

30% 数据

N

1000

N\\leq1000

N1000

M

1000

M\\leq1000

M1000

对于

100

%

100\\%

100% 的数据

M

,

N

10

5

M,N\\leq 10^5

M,N105

A

i

,

B

i

,

C

i

10

5

A_i,B_i,C_i\\le10^5

Ai,Bi,Ci105

思路分析

题目要求计算在给定行程下,为每一段铁路选择购卡或单程票的最小总花费。 关键步骤:

  • 统计每段铁路被经过的次数:
    • 给定城市序列 (

      P

      1

      ,

      P

      2

      ,

      ,

      P

      M

      P_1, P_2, \\dots, P_M

      P1,P2,,PM),相邻两次访问 (

      P

      j

      P_j

      Pj) 到 (

      P

      j

      +

      1

      P_{j+1}

      Pj+1) 经过的区间为 (

      [

      min

      (

      P

      j

      ,

      P

      j

      +

      1

      )

      ,

      max

      (

      P

      j

      ,

      P

      j

      +

      1

      )

      1

      ]

      [\\min(P_j,P_{j+1}), \\max(P_j,P_{j+1})-1]

      [min(Pj,Pj+1),max(Pj,Pj+1)1])。

    • 使用差分数组 (d) 对每个区间加 (1),最后前缀和得到每段铁路的经过次数 (k_i)。
  • 对第 (i) 段铁路,两种方案花费为:
    • 全单程票:(

      k

      i

      ×

      A

      i

      k_i \\times A_i

      ki×Ai)

    • 买卡:(

      C

      i

      +

      k

      i

      ×

      B

      i

      C_i + k_i \\times B_i

      Ci+ki×Bi)(因为

      B

      i

      <

      A

      i

      B_i < A_i

      Bi<Ai,购卡后每次花费更少) 取较小值累加即得答案。

  • 注意数据范围,使用 long long 避免溢出。
  • 代码实现

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

    int main() {
    int n, m; scanf("%d%d", &n, &m); // n:城市数,m:访问次数
    vector<int> p(m); // 访问序列
    for (int i=0; i<m; ++i) scanf("%d", &p[i]);

    vector<ll> d(n+2, 0); // 差分数组,1~n-1有效
    for (int i=0; i<m1; ++i) { // 处理每对相邻城市
    int a = p[i], b = p[i+1];
    int l = min(a,b), r = max(a,b)1; // 经过的铁路区间
    if (l <= r) { // 区间非空
    d[l] += 1; // 差分左端点+1
    d[r+1] -= 1; // 右端点后一位-1
    }
    }

    ll cnt = 0, ans = 0; // cnt:当前铁路累计次数
    for (int i=1; i<n; ++i) { // 遍历1~n-1段铁路
    cnt += d[i]; // 前缀和得到经过次数
    ll a, b, c; scanf("%lld%lld%lld", &a, &b, &c);
    ans += min(cnt * a, c + cnt * b); // 取较小花费
    }
    printf("%lld\\n", ans);
    return 0;
    }

    功能分析

  • 差分统计经过次数:利用 d[l] += 1, d[r+1] -= 1 在 O(1) 时间内标记区间,最后前缀和得到每条铁路的真实经过次数,时间复杂度 O(N+M)。
  • 逐段决策:对每条铁路,比较全单程票总价与买卡并充值总价,选择较小者累加。
  • 空间优化:只使用两个数组(访问序列 p 和差分数组 d),d 大小 N+2,满足

    10

    5

    10^5

    105数据范围。


  • 【完整系列请查看专栏】: 信奥赛C++普及组CSP-J一等奖通关刷题题单及题解: https://blog.csdn.net/weixin_66461496/category_12673810.html 点击跳转


    各种学习资料,助力大家一站式学习和提升!!!

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
    cout<<"########## 一站式掌握信奥赛知识! ##########";
    cout<<"############# 冲刺信奥赛拿奖! #############";
    cout<<"###### 课程购买后永久学习,不受限制! ######";
    return 0;
    }

    【秘籍汇总】(完整csp信奥赛C++学习资料):

    1、csp/信奥赛C++,完整信奥赛系列课程(永久学习):

    https://edu.csdn.net/lecturer/7901 点击跳转

    在这里插入图片描述

    2、CSP信奥赛C++竞赛拿奖视频课:

    https://edu.csdn.net/course/detail/40437 点击跳转 在这里插入图片描述 https://edu.csdn.net/course/detail/41081 点击跳转 在这里插入图片描述

    3、csp信奥赛高频考点知识详解及案例实践:

    CSP信奥赛C++动态规划: https://blog.csdn.net/weixin_66461496/category_13096895.html点击跳转

    CSP信奥赛C++标准模板库STL: https://blog.csdn.net/weixin_66461496/category_13108077.html 点击跳转

    信奥赛C++提高组csp-s知识详解及案例实践: https://blog.csdn.net/weixin_66461496/category_13113932.html 点击跳转

    4、csp信奥赛冲刺一等奖有效刷题题解:

    信奥赛C++普及组CSP-J一等奖通关刷题题单及题解: https://blog.csdn.net/weixin_66461496/category_12673810.html 点击跳转

    信奥赛C+普及高组csp-j初赛&复赛真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12808781.html 点击跳转

    信奥赛C++提高组csp-s初赛&复赛真题题解(持续更新): https://blog.csdn.net/weixin_66461496/category_13125089.html 点击跳转

    5、GESP C++考级真题题解:

    在这里插入图片描述

    GESP(C++ 一级+二级+三级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12858102.html 点击跳转

    在这里插入图片描述

    GESP(C++ 四级+五级+六级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12869848.html 点击跳转

    在这里插入图片描述 GESP(C++ 七级+八级)真题题解(持续更新): https://blog.csdn.net/weixin_66461496/category_13117178.html 点击跳转

    · 文末祝福 ·

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
    cout<<"跟着王老师一起学习信奥赛C++";
    cout<<" 成就更好的自己! ";
    cout<<" csp信奥赛一等奖属于你! ";
    return 0;
    }

    赞(0)
    未经允许不得转载:171主机测评 » csp信奥赛C++高频考点专项训练之前缀和&差分 --【一维差分】:海底高铁
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址