题解 P3406 【海底高铁】
实际发表时间:2020-04-22
https://www.luogu.com.cn/problem/P3406
思路:差分
我们写一个差分数组\(cnt_i\),表示\(vis_i-vis_{i-1}\)
\(vis\)就是第\(i\)段铁路的访问次数,\(vis_0=0\)。
那么\(vis_n\)
\(=vis_1-vis_1+vis_2-vis_2+\cdots+vis_{n-1}-vis_{n-1}+vis_n\)
\(=(vis_1-vis_0)+(vis_2-vis_1)+\cdots+(vis_n-vis_{n-1})\)
\(=cnt_1+cnt_2+\cdots+cnt_n\)
\(=\sum\limits_{i=1}^{n}cnt_i\).
那怎么对差分数组进行操作呢?
观察一下:
一个差分数组和原数组
0------0------0------0------0
0------0------0------0------0
城市24(经过23)
0------1------0------(-1)------0
0------1------1------ 0 ------0
城市41(经过31)
1------1------0------(-2)------0
1------2------2------ 0 ------0
城市15(经过14)
2------1------0------(-2)------(-1)
2------3------3------ 1 ------ 0
不难发现,若是从城市\(n\)~\(m\),差分数组\(cnt_{\min(n,m)}++,cnt_{\max(n,m)}--\)即可
然后每次输入\(a_i,b_i,c_i\)时判断\(vis_i \times a_i\)和\(vis_i \times b_i+c_i\)的大小即可,谁小答案就加谁
代码
#include<bits/stdc++.h>
using namespace std;
int n,m,cnt[100005],now,last,sum;
long long ans,vis[100005];//记得开longlong
struct node
{
long long a,b,c;//我喜欢写结构体,用a[i],b[i],c[i]也行
}s[100005];
long long mymin(long long x,long long y){return x<y?x:y;}//longlong的min
int main()
{
scanf("%d%d%d",&n,&m,&last);
for(int i=1;i<m;i++)
{
scanf("%d",&now);
cnt[min(now,last)]++,cnt[max(now,last)]--;//差分操作
last=now;
}
for(int i=1;i<n;i++)vis[i]=sum+=cnt[i];//计算vis[i]
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&s[i].a,&s[i].b,&s[i].c);
ans+=mymin(vis[i]*s[i].a,vis[i]*s[i].b+s[i].c);//比较
}
printf("%lld",ans);
return 0;
}
最后——
记得开long long!

浙公网安备 33010602011771号