首先需要理解一個證明:
假設我們有三個點,前兩個點價格為\(a_1,\ a_2\),距離為\(v_1,\ v_2\)
那麼就有式子:\(\frac{a_1 \times v_1}{d} + \frac{a_2 \times v_2}{d}\ 式①\),和式子\(\frac{a_1 \times v_1}{d} + \frac{a_1 \times v_2}{d} \ 式子②\)
$\rightarrow\frac{1}{d} (a_1 \times v_1+ a_2 \times v_2) => 總和 <=\frac{1}{d} (a_1 \times v_1+ a_1 \times v_2) $
假設\(a_1 > a_2\)
\(\therefore a_1 \times v_2 > a_2\times v_2\)
\(\therefore 式①>式②\)
假設\(a_1 < a_2\)
\(\therefore a_1 \times v_2 < a_2 \times v_2\)
\(\therefore 式①<式②\)
從這個推論可以得出:我們實際上是在求一個油價最長下降子序列,並且這個序列必須從1號位開始。
根據以上結論可以先暫時有以下程式碼:
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 100010;
int n, d;
int v[N], vs[N], a[N];
queue<int> p;
int main()
{
scanf("%d%d", &n, &d);
for(int i=2; i<=n; i++)
{
scanf("%d", &v[i]);
vs[i] = vs[i-1] + v[i];
}
int less = 1e9;
for(int i=1; i<=n; i++)
{
scanf("%d", &a[i]);
if(less > a[i])
{
less = a[i];
p.push(i);
}
}
long long res = 0;
int prev = p.front();
p.pop();
while(!p.empty())
{
int temp = p.front();
p.pop();
long long dis = vs[temp] - vs[prev];
res += dis * a[prev];
prev = temp;
}
cout<<res / d<<endl;
return 0;
}
但是我們發現距離正確答案差了一點點(樣例79
,程式77
)按照常識來說我們離正確答案挺近的了。問題在哪裡呢?
問題在於油是可以買多用不完的,所以我們的d不能在答案的時候才加回來,所以需要在處理過程裡買足了再計算剩多少。
但是我要變成Lazy Man了,這個題解就這樣釋出了吧。