1 条题解

  • 1
    @ 2022-8-25 10:11:37
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn = 5e5+10;
    const double eps = 1e-6;
    double a[maxn];
    double c[maxn];
    int head1,head2,tail1,tail2;
    int q1[maxn],q2[maxn];
    int n,k,L,R;
    int q3[maxn];
    inline int read(){//快读
    	int s = 0,f = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9'){
    		if(ch == '-')f = -1;
    		ch = getchar();
    	}
    	while(ch >= '0' && ch <= '9'){
    		s = s * 10 + ch - '0';
    		ch = getchar();
    	}
    	return s * f;
    }
    bool jud(double mid){//二分判断函数
    	memset(c,0,sizeof(c));
    	for(int i=1;i<=n;++i){//记录第一种相减的情况
    		c[i] = a[i] - i * mid;
    	}
    	double ans = -100000.0;
    	int head3=0,tail3=0;
    	for(int i=L+1;i<=n;++i){//单调队列维护最大值
    		while(head3 < tail3 && i - q3[head3] >= R)head3++;
    		while(head3 < tail3 && c[q3[tail3-1]] >= c[i-L])tail3--;
    		q3[tail3++] = i-L;//记录最小值的位置
    		ans = max(ans,c[i] - c[q3[head3]]);
    	}
    	head3=0,tail3=0;
    	for(int i=1;i<=n;++i){//找另一种相加的情况
    		c[i] = a[i] + i * mid;
    	}
    	for(int i=n-L;i;--i){//单调队列维护最大值
    		while(head3 < tail3 && i - q3[head3] >= R)head3++;
    		while(head3 < tail3 && c[q3[tail3-1]] >= c[i+L])tail3--;
    		q3[tail3++] = i+L;
    		ans = max(ans,c[i] - c[q3[head3]]);
    	}
    	return ans - mid * k >= 0;//判断是否成立
    }
    double calc1(){//计算长度为L的情况下的答案
    	double ans = -100000.0;
    	head1 = head2 = tail1 = tail2 = 0;//一定要初始化,不然爆掉
    	for(int i=1;i<=n;++i){
    		if(i < L){//位置不超过L的时候只维护单调性
    			while(head1 < tail1 && a[q1[tail1-1]] >= a[i])tail1--;
    			while(head2 < tail2 && a[q2[tail2-1]] <= a[i])tail2--;
    		}
    		else {//位置超过L的时候维护单调性且长度超过L的时候弹出队首
    			while(head1 < tail1 && i - q1[head1] >= L)head1++;
    			while(head2 < tail2 && i - q2[head2] >= L)head2++;
    			while(head1 < tail1 && a[q1[tail1-1]] >= a[i])tail1--;
    			while(head2 < tail2 && a[q2[tail2-1]] <= a[i])tail2--;
    		}
    		q1[tail1++] = i;
    		q2[tail2++] = i;
    		if(i >= L)//算答案
    			ans = max(ans,(double)(a[q2[head2]] - a[q1[head1]]) / (L-1+k));
    	}
    	return ans;
    }
    int main(){
    	int T = read();
    	while(T--){
    		n = read();
    		k = read();
    		L = read();
    		R = read();
    		for(int i=1;i<=n;++i){
    			scanf("%lf",&a[i]);
    		}
    		double ans = calc1();//长度刚好为L的答案
    		double l = 0,r = 1000000.0;
    		while(r - l >= eps){//二分找到最优解
    			double mid = (l + r) / 2;
    			if(jud(mid))l = mid;
    			else r = mid;
    		}
    		printf("%.4lf\n",max(ans,l));//取两种情况的最大值
    	}
    	return 0;
    }
    
    • 1

    信息

    ID
    5002
    时间
    3000ms
    内存
    512MiB
    难度
    6
    标签
    递交数
    11
    已通过
    4
    上传者