【JOI 2015 Final】铁路旅行

                                               铁路旅行

题目描述

JOI 国有 NNN 座城市,依次编号为 1,2,⋯,N1,2,\cdots ,N1,2,⋯,N ;还有 N−1N-1N−1 条可双向通行的铁路,依次编号为 1,2,⋯,N−11,2,\cdots ,N-11,2,⋯,N−1 。第 i(1≤i≤N−1)i(1\le i\le N-1)i(1≤i≤N−1) 条铁路连接着城市 iii 和 i+1i+1i+1 。

在 JOI 国有两种乘坐列车的方法:一种是使用纸质车票,另一种是使用 IC 卡。

  • 对于铁路 iii ,用纸质车票乘车一次的价格是 AiA_{i}A​i​​ 元。
  • 对于铁路 iii ,用 IC 卡乘车一次的价格是 BiB_{i}B​i​​ 元。但是,如果要用 IC 卡在第 iii 条铁路乘车的话,必须事先购买在第 iii 条铁路使用的 IC 卡。购买在第 iii 条铁路使用的 IC 卡需要花费 CiC_{i}C​i​​ 元。只要买过一次这条铁路的 IC 卡,无论在这条铁路使用 IC 卡乘车多少次都可以。

由于用 IC 卡更容易结算费用,用 IC 卡乘车总是比用纸质车票乘车便宜。也就是说,对于 i=1,2,⋯,N−1i=1,2,\cdots ,N-1i=1,2,⋯,N−1 ,总有 Ai>BiA_{i} > B_{i}A​i​​>B​i​​ 成立。由于各条铁路的 IC 卡规格各不相同,对于任意的 iii ,能在铁路 iii 使用的 IC 卡并不能在其他铁路上使用。

你准备在 JOI 国旅行,从城市 P1P_{1}P​1​​ 出发,按照 P2,P3,⋯,PMP_{2},P_{3},\cdots ,P_{M}P​2​​,P​3​​,⋯,P​M​​ 的顺序进行参观。行程由 M−1M-1M−1 天组成。第 j(1≤j≤M−1)j(1\le j\le M-1)j(1≤j≤M−1) 天的计划是从城市 PjP_{j}P​j​​ 坐火车移动到 Pj+1P_{j+1}P​j+1​​ 。可能会通过一些铁路中转。而且,你有可能多次参观同一座城市。因为 JOI 国的铁路速度很快,所以无论从哪座城市到哪座城市都能在 111 天之内到达。

现在你并没有任何一条铁路的 IC 卡。你想要买其中一些铁路的 IC 卡,从而使这次旅行所需的金额,也就是说,买 IC 卡和乘坐列车的费用总和最小。

任务

编写程序以输入 JOI 国的城市数、旅行的行程以及 JOI 国中每一条铁路的票价和 IC 卡价格,求出旅行所需费用的最小值。

输入格式

从标准输入输入数据,格式见下:

  • 第一行是两个由空格隔开的整数 NNN 和 MMM ,含义如题面所述;
  • 第二行是由空格隔开的 MMM 个整数 P1,P2,⋯,PMP_{1},P_{2},\cdots ,P_{M}P​1​​,P​2​​,⋯,P​M​​ ,表示第 j(1≤j≤M−1)j(1\le j\le M-1)j(1≤j≤M−1) 天从城市 PjP_{j}P​j​​ 坐火车到城市 Pj+1P_{j+1}P​j+1​​ ;
  • 接下来 N−1N-1N−1 行,其中第 i(1≤i≤N−1)i(1\le i\le N-1)i(1≤i≤N−1) 行有三个由空格隔开的整数 Ai,Bi,CiA_{i},B_{i},C_{i}A​i​​,B​i​​,C​i​​ ,分别表示对于铁路 iii ,用纸质车票乘车的价格为 AiA_{i}A​i​​ 元,用 IC 卡乘车的价格为 BiB_{i}B​i​​元,购买 IC 卡的价格为 CiC_{i}C​i​​ 元。

输出格式

输出到标准输出,仅一行一个整数,即以元为单位的总花费最小值。

样例

输入样例 1

4 4
1 3 2 4
120 90 100
110 50 80
250 70 130

输出样例 1

550

样例说明 1

在这种情况下,旅行总花费最小的方案如下:

  • 购买铁路 222 和 333 的 IC 卡。花去 80+130=21080+130=21080+130=210 元。
  • 第一天,使用纸质车票从城市 111 到城市 222 ,然后使用 IC 卡从城市 222 到 333 。花去 120+50=170120+50=170120+50=170 元。
  • 第二天,使用 IC 卡从城市 333 到城市 222 。花去 505050 元。
  • 第三天,使用 IC 卡从城市 222 到城市 333 ,然后使用 IC 卡从城市 333 到城市 444 。花去 50+70=12050+70=12050+70=120 元。

如果像这样乘车的话,旅行的总花费为 210+170+50+120=550210+170+50+120=550210+170+50+120=550 元,是能够达到的最小值,因此输出 550550550。

输入样例 2

8 5
7 5 3 5 4
12 5 8
16 2 1
3 1 5
17 12 17
19 7 5
12 2 19
4 1 3

输出样例 2

81

数据范围与提示

全部的输入数据满足:

  • 2≤N≤1052\le N\le 10^52≤N≤10​5​​
  • 2≤M≤1052\le M\le 10^52≤M≤10​5​​
  • 1≤Bi<Ai≤105(1≤i≤N−1)1\le B_{i} < A_{i}\le 10^5(1\le i \le N-1)1≤B​i​​<A​i​​≤10​5​​(1≤i≤N−1)
  • 1≤Ci≤105(1≤i≤N−1)1\le C_{i}\le 10^5(1\le i \le N-1)1≤C​i​​≤10​5​​(1≤i≤N−1)
  • 1≤Pj≤N(1≤j≤M)1\le P_{j}\le N(1\le j \le M)1≤P​j​​≤N(1≤j≤M)
  • Pj≠Pj+1(1≤j≤M−1)P_{j}\ne P_{j+1}(1\le j\le M-1)P​j​​≠P​j+1​​(1≤j≤M−1)

子任务 1 [202020 分]

满足以下条件:

  • 2≤N≤10002\le N \le 10002≤N≤1000
  • M=2M=2M=2
  • 1≤Bi<Ai≤1000(1≤i≤N−1)1\le B_{i} < A_{i}\le 1000(1\le i \le N-1)1≤B​i​​<A​i​​≤1000(1≤i≤N−1)
  • 1≤Ci≤1000(1≤i≤N−1)1\le C_{i}\le 1000(1\le i \le N-1)1≤C​i​​≤1000(1≤i≤N−1)

子任务 2 [303030 分]

满足以下条件:

  • 2≤N≤10002\le N \le 10002≤N≤1000
  • 2≤M≤10002\le M \le 10002≤M≤1000
  • 1≤Bi<Ai≤1000(1≤i≤N−1)1\le B_{i} < A_{i}\le 1000(1\le i \le N-1)1≤B​i​​<A​i​​≤1000(1≤i≤N−1)
  • 1≤Ci≤1000(1≤i≤N−1)1\le C_{i}\le 1000(1\le i \le N-1)1≤C​i​​≤1000(1≤i≤N−1)

子任务 3 [505050 分]

没有额外限制。

吐槽:日本的JOI就这么水吗。。。

解析:

       回到题目,我们发现只要算出每条铁路经过了多少次再比较是用纸质车票更优还是用 IC 卡更优就可以了,计算使用次数相当于区间修改单点查询,直接用树状数组就可以实现了。

代码:

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int Max=100010;
int n,m;
LL ans,a[Max],b[Max],c[Max];
int p[Max],sum[Max];
inline int get_int()
{
	int x=0,f=1;
	char c;
	for(c=getchar();(!isdigit(c))&&(c=='-');c=getchar());
	if(c=='-') {f=-1;c=getchar();}
	for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
	return x*f;
}
inline LL mn(LL x,LL y){return x > y ? y : x;}
inline int mx(int x,int y){return x > y ? x : y;}
inline void add(int pos,int x){for(;pos<=n;pos+=pos&(-pos)) sum[pos]+=x;}
inline int Q(int pos)
{
	int ans=0;
	for(;pos;pos-=pos&-pos) ans+=sum[pos];
	return ans;
}
inline void print(LL x)
{
	if(x < 0) putchar('-'),x=-x;
	if(x > 9) print(x/10);
	putchar('0' + x % 10);
}

int main()
{
	n=get_int(),m=get_int();
	for(int i=1;i<=m;i++) p[i]=get_int();
	for(int i=1;i<=n-1;i++) a[i]=get_int(),b[i]=get_int(),c[i]=get_int();
	for(int i=1;i<=m-1;i++) add(mn(p[i],p[i+1]),1),add(mx(p[i],p[i+1]),-1);
	for(int i=1;i<=n-1;i++)
	{
	  LL num = Q(i);
	  ans += mn(a[i] * num , c[i] + b[i] * num);
	}
	print(ans),putchar('\n');
	return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_38083668/article/details/81487346