zoukankan      html  css  js  c++  java
  • 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))的二分,也能水过,懒得写了

  • 相关阅读:
    __del__ 析构方法 __init__ 构造方法
    单态模式
    面向对象小练习2
    __new__ '''魔术方法
    菱形继承
    继承:多继承
    继承: .单继承
    面向对象小练习
    __init__ 魔术方法
    如何访问私有成员
  • 原文地址:https://www.cnblogs.com/shikeyu/p/13977299.html
Copyright © 2011-2022 走看看