(O(n^3))暴力
比较好写
for(int i = d;i <= n;++i)
for(int j = 1;j <= i-d+1;++j)
for(int k = j;k <= i-d+1;++k)
if(sum[i] - sum[j-1] - (sum[k+d-1]-sum[k-1]) <= p)
ans = max(ans,i-j+1);
(O(n^2))尺取法优化选择
for(int i = 1;i <= n;++i){
s += w[i];
if(i-l+1 <= d){
ans = max(ans,i-l+1); continue;
}
if(s > p){
bool flag = false;
for(int j = l;j <= i-d+1;++j){//寻找可以改变的左端点
if(s - (sum[j+d-1]-sum[j-1]) <= p){
flag = true;
ans = max(ans,i-l+1);
}
}
if(!flag) s -= w[l++];//弹队头
}
}
显然,被修改长为 (d) 的区间内的数和越大越好,于是可以尺取法过程中,单调队列 维护单调递增的 目前尺取的区间内长为 (d) 的区间和左端点优化即可
(O(n))
int p,d,w[N],l = 1,ans,q[N]; ll sum[N],s;
int main(){
n = read(); p = read(); d = read();
for(re int i = 1;i <= n;++i){
w[i] = read(),sum[i] = sum[i-1] + w[i];
}
for(re int i = 1;i <= d;++i) s += w[i];
int head = 1,tail = 1;
q[head] = d;
for(re int i = d+1;i <= n;++i){
s += w[i];
while(head <= tail && sum[i]-sum[i-d] >= sum[q[tail]] - sum[q[tail]-d])
--tail;
q[++tail] = i;
while(head <= tail && q[head]-d+1 < l) ++head;
while(s - (sum[q[head]]-sum[q[head]-d]) > p) {
s -= w[l++];
while(head <= tail && q[head]-d+1 < l) ++head;
}
ans = max(ans,i-l+1);
}
write(ans);
}
也有(O(nlog n))的二分,也能水过,懒得写了