洛谷—— P1419 寻找段落

https://www.luogu.org/problem/show?pid=1419

题目描述

给定一个长度为n的序列a_i,定义a[i]为第i个元素的价值。现在需要找出序列中最有价值的“段落”。段落的定义是长度在[S,T]之间的连续序列。最有价值段落是指平均值最大的段落,

段落的平均值=段落总价值/段落长度。

输入输出格式

输入格式:

 

第一行一个整数n,表示序列长度。

第二行两个整数S和T,表示段落长度的范围,在[S,T]之间。

第三行到第n+2行,每行一个整数表示每个元素的价值指数。

 

输出格式:

 

一个实数,保留3位小数,表示最优段落的平均值。

 

输入输出样例

输入样例#1:
3
2 2
3
-1
2
输出样例#1:
1.000

说明

【数据范围】

对于30%的数据有n<=1000。

对于100%的数据有n<=100000,1<=S<=T<=n,-10000<=价值指数<=10000。

【题目来源】

tinylic改编

 

二分一个平均值,求出a[i]-x,在长度为[s,t]的区间的和为正,则说明x可以更小、

可以用单调递增队列维护编号在i-t,i-s的区间前缀和,则需判断sum[j]-sum[i]是否>=0

 1 #include <cstdio>
 2 
 3 inline void read(int &x)
 4 {
 5     register bool __=0; register char ch=getchar();
 6     for(; ch>'9'||ch<'0'; ch=getchar()) if(ch=='-') __=1;
 7     for(; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0';
 8     x=__?((~x)+1):x;
 9 }
10 const int N(100000+5);
11 const int INF(10000);
12 int n,s,t,a[N];
13 
14 int head,tail,que[N];
15 double l,r,mid,ans,sum[N];
16 inline bool check(double x)
17 {
18     sum[0]=0;
19     for(int i=1; i<=n; ++i) sum[i]=sum[i-1]+a[i]-x;
20     head=1; tail=0;
21     for(int i=1; i<=n; ++i)
22     {
23         if(i>=s)
24         {
25             for(; head<=tail&&sum[i-s]<sum[que[tail]]; ) --tail;
26             que[++tail]=i-s;
27         }
28         if(head<=tail&&que[head]<i-t) head++;
29         if(head<=tail&&sum[i]-sum[que[head]]>=0) return 1;
30     }
31     return false;
32 }
33 
34 int Presist()
35 {
36     read(n),read(s),read(t);
37     for(int i=1; i<=n; ++i) read(a[i]);
38     for(l=-INF*1.0,r=1.0*INF; l+1e-5<r; )
39     {
40         mid=(l+r)/2.0;
41         if(check(mid)) l=mid;
42         else r=mid;
43     }
44     printf("%.3lf\n",l);
45     return 0;
46 }
47 
48 int Aptal=Presist();
49 int main(int argc,char*agrv[]){;}

 

posted @ 2017-09-23 22:09  Aptal丶  阅读(327)  评论(0编辑  收藏  举报