P3594 [POI2015]WIL-Wilcze doły

(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))的二分,也能水过,懒得写了

原文地址:https://www.cnblogs.com/shikeyu/p/13977299.html