P1419 寻找段落 单调队列+二分

题意:给出n个数,让我们求出一个最大的平均值

   求平均值的区间只能在【s,t】这样的一个范围内选取

   假如【3 ,4】,则表明可以选择一个区间大小为3或者4的,而不能选择其他大小

思路:

    首先二分答案,即:二分最大平均值。

    我们将a全部减去mid,问题转化为判断是否存在一个长度在s~t范围内的区间它的和为正,如果有说明还有更大的平均值。

    用前缀和和单调队列维护。

    然后用单调队列求出sum[i]-min(sum[i-t]~sum[i-s]),然后判断是否大于0即可。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e5+10;
 4 int a[maxn];
 5 double sum[maxn];int q[maxn];
 6 int n,s,t;
 7 bool check(double mid)
 8 {
 9     for(int i=1;i<=n;i++)
10         sum[i]=sum[i-1]+double(a[i])-mid;
11     int head=1,tail=0,q[maxn];
12     for(int i=s;i<=n;i++){
13         while(head<=tail&&sum[q[tail]]>sum[i-s]) tail--;
14         q[++tail]=i-s;
15         while(head<=tail&&q[head]<i-t) head++;
16         if(head<=tail&&sum[i]-sum[q[head]]>=0) return 1;
17     }
18     return 0;
19 }
20 int main()
21 {
22     scanf("%d%d%d",&n,&s,&t);
23     for(int i=1;i<=n;i++){
24         scanf("%d",&a[i]);
25     }
26     double L=-10000;
27     double R=10000;
28     while(R-L>=1e-5){
29         double mid=(L+R)/2;
30         if(check(mid)){
31             L=mid;
32         }
33         else{
34             R=mid;
35         }
36     }
37     printf("%.3f\n",L);
38     return 0;
39 }
View Code

 

posted @ 2020-04-11 21:01  古比  阅读(159)  评论(0编辑  收藏  举报