1. 程式人生 > 實用技巧 >題解 P3406 【海底高鐵】

題解 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
城市2~4(經過2~3)
0------1------0------(-1)------0
0------1------1------ 0 ------0
城市4~1(經過3~1)
1------1------0------(-2)------0
1------2------2------ 0 ------0
城市1~5(經過1~4)
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!