diff --git a/TangDou/Topic/PrefixAndSuffix/P5638.cpp b/TangDou/Topic/PrefixAndSuffix/P5638.cpp index 5150be6..5d67bc3 100644 --- a/TangDou/Topic/PrefixAndSuffix/P5638.cpp +++ b/TangDou/Topic/PrefixAndSuffix/P5638.cpp @@ -5,14 +5,18 @@ const int N = 1000010; #define endl "\n" int a[N], s[N]; int n, k; // n个城市,传送半径为k +int res; 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]; // 前缀和 } - int ans = s[n - 1]; // sum总和 - // 这是在枚举什么? - for (int i = k; i < n; i++) ans = min(ans, s[n - 1] - (s[i] - s[i - k])); - cout << ans << endl; + /* + 1、找出[1,n-1]的原始数组中,长度为k的子区间,加法和最大的区间段 + 2、注意:如果是枚举原始数组,那么就是 [1,n-k]是有效区间 + 3、现在遍历的是前缀和数组,为了表示a[1],需要使用的是s[1]-s[0],所以,i从0开始 + */ + for (int i = 0; i + k < n; i++) res = max(res, s[i + k] - s[i]); + cout << s[n - 1] - res << endl; } \ No newline at end of file diff --git a/TangDou/Topic/【前缀和与差分】题单.md b/TangDou/Topic/【前缀和与差分】题单.md index 9c8bea0..dd9c9bc 100644 --- a/TangDou/Topic/【前缀和与差分】题单.md +++ b/TangDou/Topic/【前缀和与差分】题单.md @@ -225,10 +225,26 @@ signed main() { 开一个大于$10$的$6$次方的数据 **思路** -- 先考虑特例 -- 由于需要最短时间,所以在有传送器的情况下使用传送器到最后一个城市 -利用前缀和,找出可以“省去”的路,相减即可 +这是一道难度入门的良心题~ + +题意很明了,可以传送一次,求$1$到$n$耗费的最少时间 + +很明显,可以贪心,最长的$k$段选择传送,其余步行 + +求两地之间用时使用前缀和,$s[i]$表示$a_1$到$a_i$之和 + +那么使用传送器可以节省时间可表示为$s[k+i]-s[i]$ (有效区间$[i+1,i+k]$) + +扫一遍找到节省时间最大值,答案即是$1$到$n$之间步行用时减去传送节省时间 +然而稍不注意就只有$92$分,似乎坑到了一部分人(比如本蒟蒻) + +![](https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/BlogImages/202312181334534.png) + +原因很简单,$s[k+i]-s[i]$中的$i$要从$0$开始循环而不是从$1$开始 +显而易见,若$k=1$,那么$s[1+1]-s[1]$表示的是$2 , 3$两地之间用时 +所以如果从$1$开始循环就会漏掉从$1$地到$1+k$地之间的用时 +从$0$开始循环就可以$AC$了!