1. 程式人生 > >洛谷—— P1419 尋找段落

洛谷—— P1419 尋找段落

單調遞增 printf head 格式 n+2 前綴和 最大的 1.0 需要

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[]){;}

洛谷—— P1419 尋找段落