平均数

题目链接:平均数

考虑两种算法:

1、二分

每次判断能不能满足存在长度大于m的子串的平均值>=mid【可以考虑使用前缀和优化】

这个思路比较简单,代码:

 1 #define INF 0x7fffffff
 2 #include<cstdio>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 const int MAXN=100010;
 7 long long a[MAXN],sum[MAXN];
 8 int n,m;
 9 inline int read()
10 {
11     int x=0,w=1;
12     char c=getchar();
13     while(c>'9'||c<'0'){if(c=='-') w=-1; c=getchar();}
14     while(c<='9'&&c>='0'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
15     return w*x;
16 }
17 bool judge(int mid)
18 {
19     long long minn=INF;
20     for(int i=1;i<=n;++i)
21     {
22        sum[i]=sum[i-1]+a[i]-mid;
23        if(i>=m)
24        {
25          minn=min(minn,sum[i-m]);
26          if(sum[i]>=minn)
27          return true;
28        }
29     }
30     return false;
31 }
32 int main()
33 {
34     n=read(),m=read();
35     for(int i=1;i<=n;++i)
36     a[i]=read(),a[i]*=10000;
37     int l=0,r=20000000;
38     while(l<r)
39     {
40       int mid=(l+r)>>1;
41       if(judge(mid)) l=mid+1;
42       else r=mid-1;
43     }
44     if(!judge(l)) --l;
45     printf("%d\n",l/10);
46     return 0;
47 }
二分答案解法

2、数学推导

*发现很多题目跑的最快的算法都是别人的,比方说这题有人说是可以O(N)的


先求部分和S(x),然后连续子序列平均值就转化为S-x平面上的斜率:ave(x,y)=(S(y)-s(x-1))/(y-x+1)。考虑x<y<z的三个点如果S(y)是上凸的,则这个点一定没贡献。所以有用的点构成一个下凸的折线

用一个队列维护这个折线,加入新点时(如当前点为i,则新点为i-m),如果与队尾2个点形成上凸,则删除队尾点。如果队首2个点与当前点形成上凸,同理删除队首点。最后每次队首元素都是与点i斜率最大的点,再求最值就行了


代码:

 1 #include <iostream>
 2 #include <cmath>
 3 #define N 100005
 4 typedef long long ll;
 5 using namespace std;
 6 ll n,m,s[N];
 7 double ans=0.0;
 8 ll q[N],t,h;   // 队列
 9 
10 double k(ll x,ll y){  // 计算s[x],s[y]的斜率
11     return (s[y]-s[x]+0.0)/(y-x);
12 }
13 int main() {
14     cin>>n>>m;
15     for (ll i=1,x;i<=n;i++){
16         cin>>x; s[i]=s[i-1]+x;
17     }
18 
19     for (ll i=m;i<=n;i++){
20         while (t-h>=2 && k(i-m,q[t-1])<k(i-m,q[t-2])) t--;   // 删除上凸点
21         q[t++]=i-m;  // 入队
22         while (t-h>=2 && k(i,q[h])<k(i,q[h+1])) h++;  // 移动最大斜率点
23         ans=max(ans,k(i,q[h]));
24     }
25 
26     cout<<(ll)floor(ans*1000)<<endl;
27     return 0;
28 }
O(N)解法

 


 

posted @ 2019-08-04 20:32  LyingFlat666  阅读(159)  评论(0编辑  收藏  举报