2019.2.15 t3 平均值

 

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <cctype>
 6 #include <cstring>
 7 #include <queue>
 8 #include <algorithm>
 9 using namespace std;
10 
11 #define res register int
12 inline int read()
13 {
14     int x(0),f(1); char ch;
15     while(!isdigit(ch=getchar())) if(ch=='-') f=-1;
16     while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
17     return f*x;
18 }
19 
20 inline int max(int x,int y){return x>y?x:y;}
21 inline double max(double x,double y){return x>y?x:y;}
22 inline int min(int x,int y){return x<y?x:y;}
23 
24 const int N=50000+5;
25 int a[N],n,k,L,R,t;
26 int d[N],q[N],q1[N];
27 double s[N];//差分数组,前缀和数组 
28 
29 inline bool check(double m)
30 {
31     int l=1,r=0; //把i看成右端点(此处取得最大s),找s[i]最小的左端点 
32     double ans(-1e9-7);
33     for(res i=1 ; i<=n ; i++)
34     {
35         if(i-L+1<=0) continue;
36         while(l<=r && s[q[r]]>=s[i-L+1]) r--;
37         //加入i-L+1(和之前比右端点向右挪了一位) 
38         q[++r]=i-L+1;
39         while(i-q[l]+1>R && l <= r) l++;//排除非法 
40         if(l<=r) ans=max(ans,s[i]-s[q[l]]);
41     }
42     return ans>m*k;
43 }
44 
45 inline bool judge(double m)
46 {
47     for(res i=1 ; i<=n ; i++)
48         s[i]=s[i-1]+(double)d[i]-m;    
49     return check(m);
50 }
51 int main()
52 {
53     freopen("average.in","r",stdin);
54     freopen("average.out","w",stdout);
55     int T=read();
56     while(T--)
57     {
58         double maxn(0.0);
59         n=read(); k=read(); L=read(); R=read();
60         for(res i=1 ; i<=n ; i++) a[i]=read();
61         for(res i=1 ; i<=n ; i++) d[i]=a[i]-a[i-1];
62         double l=0,r=1e9+7;
63         int head(1),tail(0),head1(1),tail1(0);
64         double ans(-100000000.0);
65         //特殊情况,取得最大值与最小值的两端点之间的距离小于L 
66         //此处用线段树也可以 
67         for(res i=1 ; i<=n ; i++)
68         {
69             while((head<=tail) && (a[q[tail]]>a[i])) tail--;
70             q[++tail]=i;
71             while((head1<=tail1) && (a[q1[tail1]]<a[i])) tail1--;
72             q1[++tail1]=i;
73             while((head<=tail) && i-q[head]+1 > L) head++;
74             while((head1<=tail1) &&i-q1[head1]+1 > L) head1++;
75             ans=max(ans,(double)(a[q1[head1]]-a[q[head]]) / (double)(L+k-1));
76         }
77         while(r-l>0.0000001)
78         {
79             double mid=(l+r)/2;
80             if(judge(mid)) l=mid,ans=max(ans,l);
81             else r=mid;
82         }
83         //翻转过来,再求一遍,即在刚才的右端点处取得最小s 
84         reverse(a+1,a+n+1);
85         for(res i=1 ; i<=n ; i++) d[i]=a[i]-a[i-1];
86         l=0,r=1e9+7;
87         while(r-l>0.0000001)
88         {
89             double mid=(l+r)/2.0;
90             if(judge(mid)) l=mid,ans=max(ans,l);
91             else r=mid;
92         }                
93         printf("%.4lf\n",ans); 
94     }    
95     return 0;
96 }
View Code

 

posted @ 2019-02-15 21:13  孑行  阅读(114)  评论(0编辑  收藏  举报