P9749 [CSP-J 2023] 公路
P9749 [CSP-J 2023] 公路
题目范围
\(1 \leq n \leq 10^5\),\(1 \leq d \leq 10^5\),\(1 \leq v_i \leq 10^5\),\(1 \leq a_i \leq 10^5\)。
解题思路
\(d\): 车每升油可以前进的距离
\(v_i\): 站点间的距离
\(a_i\): 加油的价格
有 \(n-1\) 段路,油箱是无限大的。如果分段考虑买油量,答案会偏大,因为加油量是整数且油是可以延续的。
因此,我们从整体出发,考虑每段路必须买的油,即上一段路“多余”的油用完后,在下一站到前还要用的油量。
引入前缀和 prv[i] 表示前 \(i\) 段路的总路程,\(\lceil \frac{\text{prv}[i]}{d} \rceil\) 表示到达 \(i+1\) 站点至少需要的油量,\(\lceil \frac{\text{prv}[i-1]}{d} \rceil\) 表示到达第 \(i\) 站至少需要的油,两者相减即表示在 \(i \sim i+1\) 段必须买的油。
考虑到价格,我们可以在第 \(i+1\) 站以前的最便宜的站把这个油买了(贪心),即最终结果就是对每一段新增油量乘以前面的最小油价后求和。
复杂度分析
时间复杂度:\(O(n)\)
空间复杂度:\(O(n)\)
代码实现
void solve(){
int n,d;
cin>>n>>d;
vector<int>v(n); //1 ~ n-1
vector<LL>prv(n,0);// prv[1]=pre[0]+v[1]
vector<int>a(n+1);
rep(i,1,n) cin>>v[i];
rep(i,1,n+1) cin>>a[i];
rep(i,1,n) prv[i]=prv[i-1]+v[i];// 最多为前n-1段路
int mn=a[1];//维护当前遇见的最低油价
LL res=0;
LL need=0;
rep(i,1,n){
need=(prv[i]+d-1)/d - (prv[i-1]+d-1)/d; //新增的必须买的油量
//a/b向上取整为(a+b-1)/b
mn=min(a[i],mn);
res+=mn*need;
}
cout<<res<<'\n';
}

浙公网安备 33010602011771号