1 条题解
-
1
#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
- 上传者