题解 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!

posted @ 2020-08-29 10:39  ADay526  阅读(192)  评论(0)    收藏  举报