main
黄海 2 years ago
parent 078b1c337d
commit 9659920ad8

@ -1,22 +1,24 @@
#include <bits/stdc++.h>
using namespace std;
const int N = 1000010;
#define int long long
#define endl "\n"
const int N = 1000010;
int n, k;
int a[N], s[N];
int n, k; // n个城市传送半径为k
int res;
int ans = LONG_LONG_MAX; // 预求最小先设最大
signed main() {
cin >> n >> k; // n个城市传送半径为k
for (int i = 1; i < n; i++) { // 以起点为线段命名的编号,所以1~n共n个城市,其实是n-1条线段
cin >> a[i]; // 走这条路要耗费时间a[i]
s[i] += s[i - 1] + a[i]; // 前缀和
cin >> n >> k;
for (int i = 2; i <= n; i++) { // i代表第i个城市
cin >> a[i]; // a[i]代表第i-1个城市到第i个城市需要的时间
s[i] = s[i - 1] + a[i]; // 利用前缀存储从第1个城市到第i+1个城市的累积时间
}
// 感悟:代码越多,可读性越强
for (int i = 1; i <= n; i++) { // 遍历每个城市
int far = i + k; // 传送到最远的点
if (far >= n) far = n; // 最远不能超过n点
int time = s[i] + s[n] - s[far]; // s[n]-s[far]= 剩余道路需要走的时间,s[i]:前面道路需要走的时间
ans = min(ans, time); // 取最小值
}
/*
1[1,n-1]k
2, [1,n-k]
3a[1],使s[1]-s[0],i0
*/
for (int i = 0; i + k < n; i++) res = max(res, s[i + k] - s[i]);
cout << s[n - 1] - res << endl;
cout << ans << endl; // 输出
}

@ -226,28 +226,51 @@ signed main() {
**思路**
这是一道难度入门的良心题~
![](https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/BlogImages/202312181353674.png)
题意很明了,可以传送一次,求$1$到$n$耗费的最少时间
上图是一个$n = 6$的样例。从城市$1$到城市$6$,需要$3+2+4+5+4=18$天。
很明显,可以贪心,最长的$k$段选择传送,其余步行
假如传送器的半径为$2$。可以逐个枚举。
求两地之间用时使用前缀和,$s[i]$表示$a_1$到$a_i$之和
- 如果在城市$1$使用传送器,则一下子可到达城市$3$,然后城市$3$到城市$6$,需要$13$天。这种情况下从城市$1$到城市$6$,需要$13$天。
那么使用传送器可以节省时间可表示为$s[k+i]-s[i]$ (有效区间$[i+1,i+k]$)
- 如果在城市$2$使用传送器,则从城市$1$先用$3$天的时间到达城市$2$,再用传送器到达城市$4$,从城市$4$到城市$6$需要$9$天。这种情况下从城市$1$到城市$6$,共需要$3 + 9 = 12$天。
扫一遍找到节省时间最大值,答案即是$1$到$n$之间步行用时减去传送节省时间
然而稍不注意就只有$92$分,似乎坑到了一部分人(比如本蒟蒻)
- 如果在城市$3$使用传送器,则从城市$1$到城市$3$需要$5$天,从城市$3$使用传送器一下子到达城市$5$,从城市$5$到城市$6$需要$4$天。这种情况下从城市$1$到城市$6$,共需要$5+4=9$天。
![](https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/BlogImages/202312181334534.png)
- 如果在城市$4$使用传送器,则从城市$1$到城市$4$需要$9$天,从城市$4$使用传送器一下子到达城市$6$。这种情况下从城市$1$到城市$6$,共需要$9$天。
原因很简单,$s[k+i]-s[i]$中的$i$要从$0$开始循环而不是从$1$开始
显而易见,若$k=1$,那么$s[1+1]-s[1]$表示的是$2 , 3$两地之间用时
所以如果从$1$开始循环就会漏掉从$1$地到$1+k$地之间的用时
从$0$开始循环就可以$AC$了!
- 如果在城市$5$使用传送器,则从城市$1$到城市$5$需要$14$天,从城市$5$使用传送器一下子到达城市$6$。这种情况下从城市$1$到城市$6$,共需要$14$天。
所以在城市$3$或城市$4$使用传送器,可以使得总共花费的时间最少。
**$Code$**
```cpp {.line-numbers}
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
const int N = 1000010;
int n, k;
int a[N], s[N];
int ans = LONG_LONG_MAX; // 预求最小先设最大
signed main() {
cin >> n >> k;
for (int i = 2; i <= n; i++) { // i代表第i个城市
cin >> a[i]; // a[i]代表第i-1个城市到第i个城市需要的时间
s[i] = s[i - 1] + a[i]; // 利用前缀存储从第1个城市到第i+1个城市的累积时间
}
// 感悟:代码越多,可读性越强
for (int i = 1; i <= n; i++) { // 遍历每个城市
int far = i + k; // 传送到最远的点
if (far >= n) far = n; // 最远不能超过n点
int time = s[i] + s[n] - s[far]; // s[n]-s[far]= 剩余道路需要走的时间,s[i]:前面道路需要走的时间
ans = min(ans, time); // 取最小值
}
cout << ans << endl; //
}
```
#### [$P1719$ 最大加权矩阵](https://www.luogu.com.cn/problem/P3406)

Loading…
Cancel
Save