首页 > 代码库 > 洛谷P3406 海底高铁

洛谷P3406 海底高铁

题目背景

大东亚海底隧道连接着厦门、新北、博艾、那霸、鹿儿岛等城市,横穿东海,耗资1000亿博艾元,历时15年,于公元2058年建成。凭借该隧道,从厦门可以乘坐火车直达台湾、博艾和日本,全程只需要4个小时。

题目描述

该铁路经过N个城市,每个城市都有一个站。不过,由于各个城市之间不能协调好,于是乘车每经过两个相邻的 城市之间(方向不限),必须单独购买这一小段的车票。第i段铁路连接了城市i和城市i+1(1<=i<N)。如果搭乘的比较远,需要购买多张 车票。第i段铁路购买纸质单程票需要Ai博艾元。

虽然一些事情没有协调好,各段铁路公司也为了方便乘客,推出了IC卡。对于第i段铁路,需要花Ci博艾元的工本费购买一张IC卡,然后乘坐这段铁路 一次就只要扣Bi(Bi<Ai)元。IC卡可以提前购买,有钱就可以从网上买得到,而不需要亲自去对应的城市购买。工本费不能退,也不能购买车票。 每张卡都可以充值任意数额。对于第i段铁路的IC卡,无法乘坐别的铁路的车。

Uim现在需要出差,要去M个城市,从城市P1出发分别按照P1,P2,P3...PM的顺序访问各个城市,可能会多次访问一个城市,且相邻访问的城市位置不一定相邻,而且不会是同一个城市。

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

输入输出格式

输入格式:

第一行两个整数,N,M。

接下来一行,M个数字,表示Pi

接下来N-1行,表示第i段铁路的Ai,Bi,Ci

输出格式:

一个整数,表示最少花费

输入输出样例

输入样例#1:
9 103 1 4 1 5 9 2 6 5 3200 100 50300 299 100500 200 500345 234 123100 50 100600 100 1450 400 802 1 10
输出样例#1:
6394

说明

2到3以及8到9买票,其余买卡。

对于30%数据 M=2

对于另外30%数据 N<=1000 ,M<=1000

对于100%的数据 M,N<=100000,Ai,Bi,Ci<=100000

 

用前缀和数组算出每条路的经过次数,最后扫描每条路,决定买不买卡。

 

代码第35行的地方,我第一次写了  min( (long long)a*p, (long long)c+b*p) ,a b c都是int。  问题很明显:b*p花式越界。

嗨呀好气呀

 

 1 /*By SilverN*/ 2 #include<iostream> 3 #include<cstdio> 4 #include<cmath> 5 #include<cstring> 6 #include<algorithm> 7 #define LL long long 8 using namespace std; 9 int read(){10     int x=0,f=1;char ch=getchar();11     while(ch<0 || ch>9){if(ch==-)f=-1;ch=getchar();}12     while(ch>=0 && ch<=9){x=x*10+ch-0;ch=getchar();}13     return x*f;14 }15 const int mxn=240000;16 int n,m;17 int smm[mxn];18 LL a,b,c;19 void clc(int a,int b){20     if(a>b)swap(a,b);21     smm[a]++;smm[b]--;22     return;23 }24 int main(){25     n=read();m=read();26     int i,j;27     int last,p;28     last=read();29     for(i=2;i<=m;i++){p=read();clc(last,p);last=p;}30     p=0;31     long long ans=0;32     for(i=1;i<n;i++){33         p+=smm[i];34         a=read();b=read();c=read();35         long long tmp=min(a*p,b*p+c);36         ans+=tmp;37     }38     cout<<ans<<endl;39     return 0;40 }

 

洛谷P3406 海底高铁