1 solutions
-
0
简单来说,这道题就是这样滴:
在数组 a 中确定一个左端点 l 和一个右端点 r。
记录 为 到 的和。
如果 大于一个神奇的式子,那么就算出 的值,最后输出最大值就行了。
到 的和可以使用前缀和解决,时间复杂度 。
然后我就写出了下面一份代码:#include <bits/stdc++.h> using namespace std; long long p[300005],sum[300005],a,b,c,n,maxx = -1;//开long long是好习惯,虽然我不知道不开行不行 int main(){ cin >> n >> a >> b >> c; for(long long i = 1;i <= n;i++){ cin >> p[i]; sum[i] = sum[i-1] + p[i];//前缀和,sum[i]存储的是p[1] ~ p[i]的和 } for(long long l = 1;l <= n;l++){ for(long long r = l;r <= n;r++){ if(sum[r] - sum[l-1] > a * (b * r - c * l)){//sum[r] - sum[l-1]代表了p[l] ~ p[r]的和 maxx = max(maxx,r-l+1);//满足式子就求最大值呗 } } } cout << maxx; return 0; }
然后成功的 TLE 了,只拿到了 60 分。
为什么呢?题目中的 n 达到了 ,所以说 是肯定 AC 不了滴!
我们需要把时间复杂度压缩到近似于 。 让我们分析一下题目,已知我们求的是 的最大值,所以 r 和 l 的差值一定要尽量的大,而这个奇奇怪怪的式子又告诉我们,如果 r 和 l 的差值越大,条件就越难满足,如果不能满足,就是差值太大了。
所以说,一个名叫二分的东东就很有用了。
建立一个数组 f,TA 存储的是左端点耗费的权值。
其中 sum 是前缀和数组。
为肾木呢?
序列中的第 l 至 r 项之和大于 。 也就是说序列中的第 1 至 r 项之和减去序列中的第 1 至 l−1 项之和大于 。
所以 大于 0。
所以 大于 。
其中右端点的部分就是 。 左端点的部分是 。
如果 比 还要大,那肯定取 啊, 足足能大 1 啊!
接下来,用 i 枚举 1∼n,表示 1∼i 中的最大值就行了。
- 1
Information
- ID
- 158
- Time
- 1000ms
- Memory
- 256MiB
- Difficulty
- 5
- Tags
- # Submissions
- 1
- Accepted
- 1
- Uploaded By