题解:ABC267C - Index × A(Continuous ver.)
·题目
C - Index × A(Continuous ver.)。
·难度
算法难度:入门
思维难度:入门
调码难度:普及
综合评价:简单
·算法
滚动求值优化
·思路
如果每次遍历开始位置,并向后推移m位求和O(nm)会超时。因此考虑优化。
从原来的式子a[i]*1+a[i+1]*2+a[i+2]*3+...+a[i+m-1]*m(即从a的第i项开始到第i+m+1项结束取出b)变为a[i]*0+a[i+1]*1+a[i+2]*2+...+a[i+m-1]*(m-1)+a[i+m]*m(即从a的第i+1项开始到第i-m项结束取出b),两者之间差了a[i]+a[i+1]+a[i+2]+...+a[i+m-1]-a[i+m]*m,因此在每次遍历起始点i时维护sum表示a[i]+a[i+1]+a[i+2]+...+a[i+m-1]的值,每次更新时减去差值即可。此时时间复杂度是O(n+m),可以AC。
另请参见:题解:ABC267C - Index × A(Continuous ver.)(不要怀疑,就是我录的)。
·代码
#include<bits/stdc++.h>
#define N 220000
using namespace std;
long long ans=-((1LL)<<60),sum=0,tmp=0;
//ans表示最终答案,sum表示的是当前的i到i+m-1之间所有a的和,tmp表示从a的当前的i到i+m-1项取出的数形成b此时的答案
int a[N]={},m=0,n=0;
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
//输入
for(int i=1;i<=m;i++){
sum+=a[i];
tmp+=a[i]*1LL*i;
}
//sum和tmp初始值
for(int i=1;i<=n-m+1;i++){
ans=max(ans,tmp);
//用当前答案(tmp)更新ans
tmp=tmp-sum+a[i+m]*1LL*m;
//更新tmp,就是往前滚动,已将出现的a数乘数减去一,形象的写成把整体减去一次sum,之后把最后面的数添加进来(其实也就是减去差值)
sum=sum-a[i]+a[i+m];
//更新sum,去掉开头,加上新的结尾
}
printf("%lld\n",ans);
//输出答案
return 0;
}
·注意
开long long(要不然会WA)。
数据范围不要写错。