(不要小看了這個資料範圍)
首先明確一下題意,對於樣例中的訪問順序3 1 4 1 5 9 2 6 5 3,它意味著:(數字代表城市)
從 3 出發,依次經過2~3間的鐵路,1~2間的鐵路,到達1;
再從 1 出發,依次經過1~2,2~3,3~4之間的鐵路,到達4,以此類推.
顯然,對於任意一段鐵路,可以根據訪問順序統計出來經過他們的次數,而僅僅通過這個次數就可以計算出來是直接買票還是買卡後買票比較划算.
設第i段鐵路經過的次數為p[i],那麼遍歷鐵路1~n-1(注意只有n-1段鐵路,第i段鐵路從i城到達i+1城),使ans += min(p[i] * a[i], p[i] * b[i] + c[i])即可.
現在逐個解決問題,如何統計每一段次數經過的次數?
暴力方法是讀入起點和終點城市,然後讓其間涉及到的p[i]加一,這裡明顯會tle,
所以使用差分,差分是一種與字首和相對的預處理方法:
對於讀入的一對起點城市from和終點城市to,有(根據題意from 不會與to相等)
cin >> from讀入訪問所有訪問順序後,進行字首和處理:;
for(int i = 2; i <= m; i++)
for(int i = 1; i <= n; i++) p[i] += p[i - 1];此時,p[i]就可以表示通過鐵路i的次數了,這裡的複雜度(為o(n))比暴力統計(最壞情況o(n2),即這個人從1到n反覆橫跳)小很多.
這裡的差分應當是很容易理解的.
#include #includeac code#include
#include
using
namespace
std;
int n, m, p[100010], a[100010], b[100010], c[100010
];unsigned
long
long
ans;
void calc()
intmain()
for(int i = 1; i <= n; i++) p[i] += p[i - 1
];
for(int i = 1; i < n; i++) cin >> a[i] >> b[i] >>c[i];
calc();
cout
<< ans <
return0;
}
在我ac之前,這裡還有乙個我個人所犯的錯誤.
儘管為了防爆給ans開了long long,當我發現陣列p只需要int就可以儲存時就認為這樣寫很合理:
void結果犯了個初學者的錯誤,右側表示式的最高等級是int,但實際上int的乘積是需要long long來正確儲存的,需要強制型別轉換.即calc()
voidcalc()
洛谷P3406 海底高鐵
大東亞海底隧道連線著廈門 新北 博艾 那霸 鹿兒島等城市,橫穿東海,耗資1000億博艾元,歷時15年,於公元2058年建成。憑藉該隧道,從廈門可以乘坐火車直達台灣 博艾和日本,全程只需要4個小時。該鐵路經過n個城市,每個城市都有乙個站。不過,由於各個城市之間不能協調好,於是乘車每經過兩個相鄰的城市之...
P3406 海底高鐵 差分
題目背景 大東亞海底隧道連線著廈門 新北 博艾 那霸 鹿兒島等城市,橫穿東海,耗資1000億博艾元,歷時15年,於公元2058年建成。憑藉該隧道,從廈門可以乘坐火車直達台灣 博艾和日本,全程只需要4個小時。題目描述 該鐵路經過n個城市,每個城市都有乙個站。不過,由於各個城市之間不能協調好,於是乘車每...
洛谷 P3406 海底高鐵 模擬
大東亞海底隧道連線著廈門 新北 博艾 那霸 鹿兒島等城市,橫穿東海,耗資1000億博艾元,歷時15年,於公元2058年建成。憑藉該隧道,從廈門可以乘坐火車直達台灣 博艾和日本,全程只需要4個小時。該鐵路經過n個城市,每個城市都有乙個站。不過,由於各個城市之間不能協調好,於是乘車每經過兩個相鄰的城市之...