1 条题解
-
0
题目目的说明
我们需要找出一段长度为的连续子序列,使得他们的加权和最大。
最最最暴力的方法
不就是枚举吗?枚举长度为的序列,每次移动一格。如下图。
暴力的代码实现 O(nm)
#include<iostream> using namespace std; const int N = 200050; long long b[N]; long long res = 0; int n , m; int main() { cin >> n >> m; for(int i = 1; i <= n; i++) { cin >> b[i]; } for(int i = 1; i <= n - m + 1; i++) { long long tmp = 0; for(int j = i; j <= i + m - 1; j++) { tmp += (j - i + 1) * b[j]; //题目要求加权求和 } res = max(tmp, res); } cout<<res; return 0; }
一交!AC!!!!(
我在想屁吃) 被超时了!所以我们就来优化了
我们要根据前面那张图来找找规律如下图所示
所以我们得到了最终方案
我们用前缀和先预处理一次这样的话,我们在求区间和的时候我们就达到了o(1)的时间复杂度。其他思路还是一样的
代码实现O(n)
#include<iostream> #include<cstdio> using namespace std; const int N = 200050; long long b[N]; long long f[N]; long long a[N]; long long n , m; int main() { cin >> n >> m; //读入数据并预处理前缀和 for(int i = 1; i <= n; i++) { cin >> b[i]; a[i] = a[i - 1] + b[i]; } // 初始化我们的第一个求和数组 for(int i = 1; i <= m ; i++) { f[1] += i * b[i]; } long long res = f[1]; //把第一个值先加进去 //然后开始递推计算 for(int i = 2; i <= n - m + 1; i++) { f[i] = f[i - 1] - (a[i - 2 + m] - a[i - 2]); f[i] += m * b[i + m - 1]; res = max(res, f[i]); } printf("%lld", res); return 0; }
信息
- ID
- 20972
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 8
- 标签
- (无)
- 递交数
- 73
- 已通过
- 11
- 上传者