首先暴力很好搞,但是优化的话就不会了。放弃QWQ。
做法1:二分答案
然后发现平均值是$ave=\frac{sum}{len}$,这种形式似乎可以二分答案?把$len$移到左边。
于是二分$ave$,去找数列有没有区间和大于等于其$len$乘以$ave$的,然后卡住了。。
有一个很巧的转化,把每个数都减去一个$ave$,然后任意区间和就相当于把$ave$累加了$len$次。
于是乎只要看区间和$S-len*ave$是否大于等于0就可以了。
存在这样一个区间就说明$ave$可以更大,否则要小。查找存在性是一个简单的前缀和dp。
$O(nlogn)$。
poj精度死活卡不过去。
看来技巧还不够。
于是一气之下把所有double型全换成long long,也就是把小数点后五位通通看成整数,然后运算,最后除以100。
唉。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #define dbg(x) cerr << #x << " = " << x <<endl 7 using namespace std; 8 typedef long long ll; 9 typedef double db; 10 typedef pair<int,int> pii; 11 template<typename T>inline T _min(T A,T B){return A<B?A:B;} 12 template<typename T>inline T _max(T A,T B){return A>B?A:B;} 13 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;} 14 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;} 15 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;} 16 template<typename T>inline T read(T&x){ 17 x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1; 18 while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x; 19 } 20 const int N=1e5+7; 21 const db eps=1e-7; 22 ll A[N],s[N]; 23 ll L=1,R,mid; 24 int n,l; 25 inline bool check(ll ave){ 26 for(register int i=1;i<l;++i)s[i]=s[i-1]+A[i]-ave; 27 ll minx=1e16; 28 for(register int i=l;i<=n;++i){ 29 MIN(minx,s[i-l]);s[i]=s[i-1]+A[i]-ave; 30 if(s[i]-minx>=0)return 1; 31 } 32 return 0; 33 } 34 35 int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout); 36 read(n),read(l); 37 for(register int i=1;i<=n;++i)A[i]=read(A[i])*100000,MAX(R,A[i]); 38 while(L<R){ 39 mid=L+R+1>>1; 40 if(check(mid))L=mid; 41 else R=mid-1; 42 } 43 printf("%lld",(L/100)); 44 return 0; 45 }View Code