2 条题解
-
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; }
-
0
定义
$$w(l,r)=\max\{a_k|l\le k\le r\}-\min\{a_k|l\le k\le r\} $$则易证 满足区间包含单调性。(即,)
定义
则易证 。
定义
则易证 。
我们现在要求
$$\max\{\frac{w_m}{m-1+K}|L\le m\le R\} \\= \max\{\max\{\frac{W_m}{m-1+K}|L\le m\le R\},\frac1{L-1+K}\max\{W_m|1\le m<L\}\} $$对于第二类贡献,我们可以一次扫描线 + 单调队列解决。
考虑 的贡献。
考虑二分答案。
设要 check 是否有 。
即是否有
。
即是否有
$\max\{\max\{(a_l+lx)-(a_r+rx),(a_r-rx)-(a_l-lx)\}|L\le r-l+1\le R\}\ge xK$。
即是否有
$\max\{b_l-b_r|L\le r-l+1\le R\}\ge V\lor\max\{c_r-c_l|L\le r-l+1\le R\}\ge V$。
这个可以单轮 解决。
众所周知单调队列狗都不写,因此我们单调队列真香。总复杂度 。
- 1
信息
- ID
- 4476
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 7
- 标签
- (无)
- 递交数
- 42
- 已通过
- 9
- 上传者