思路
注意到这里是求某段区间的和,而且不修改,那肯定是用前缀和了 sum[ n ]表示
接下来就是要选择两个长度为k的区间求最大,最原始的思路当然是枚举每个可能的区间更新最大值,代码就是
ll ans = 0; for(int i = k ; i <= n-k ; ++i){ for(int j = i+k ; j <= n ; ++j){ ans = max(ans,a[i]-a[i-k] + a[j] - a[j-k]); } }
结果当然是T的果断,那肯定要想想怎么优化。
如果 两段区间分别是 (L,L+1,.....L+k) (R,R+1,.....,R+k)
假设 X为 两个区间的中间点,既 X >= L+k && X <= R
如果要取得最优解的话必定要满足区间 (L,L+1,.....L+k)为 1 ~ X 上 和最大和的区间,(R,R+1,.....,R+k) 为X ~ n 上最大和的区间,于是我们可以这样想,不断枚举 X的值 寻找 这样的两个区间。
那代码就出来了,结合代码理解一下吧
代码
#include<bits/stdc++.h> using namespace std; typedef long long ll; inline ll read(){ ll s = 0, w = 1; char ch = getchar(); while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); } while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar(); return s * w; } ll a[200005]; int main(){ int t = read(); while(t--){ int n = read(),k = read(); for(int i = 1 ; i <= n ;++i){ a[i] = read(); a[i] += a[i-1]; } ll ans = -1e18,last = -1e18; for(int i = k ; i+k <= n ; ++i){ last = max(last , a[i] - a[i-k]); //last表示 1 ~ i内最优的区间 ans = max(ans , last + a[i+k] - a[i]); } cout<<ans<<endl; } }