zoukankan      html  css  js  c++  java
  • Luogu P1404 平均数 题解

    闲扯

    蒟蒻又来做例题了。。。

    这道题调了半天,结果是维护前缀和的最小值的时候弄成了原数组的值。。。。

    题面

    题面

    Solution

    使用二分答案,将求解转化为判定。

    对于当前二分出的平均值,我们要确定它的合法性,我们可以将所有数先减去平均值。

    这时我们相当于是要找去一段区间,使得它的和大于 (0)

    我们慢慢来解决这个问题。

    1. 对于没有长度限制,找出一个区间,使它的和最大。

      ​ 这是一个经典问题,只需要 (O(n)) 扫描这个区间,将新的数加入子段。当和为负值,就将子段清空。扫描过程中出现的最大子段和即为所求。

    2. 对于有长度限制,找出一个区间,使它的和最大。

      ​ 子段和转化为前缀和相减,则有: (maxlimits_{i-jgeq L}(A_{j+1},A_{j+1},cdots,A_i)=maxlimits_{Lleq ileq n}(sum_i-minlimits_{0leq jleq i-L} sum_j))

      ​ 随着 (i) 的增长, (j) 的取值范围每次只会增加 (1) 。所以我们每次更新一下最小值即可。

    Code

    #include<bits/stdc++.h>
    #define del(a,i) memset(a,i,sizeof(a))
    #define ll long long
    #define inl inline
    #define il inl void
    #define it inl int
    #define ill inl ll
    #define re register
    #define ri re int
    #define rl re ll
    #define mid ((l+r)/2)
    #define lowbit(x) (x&(-x))
    #define INF 0x3f3f3f3f
    using namespace std;
    template<class T>il read(T &x){
    	int f=1;char k=getchar();x=0;
    	for(;k>'9'||k<'0';k=getchar()) if(k=='-') f=-1;
    	for(;k>='0'&&k<='9';k=getchar()) x=(x<<3)+(x<<1)+k-'0';
    	x*=f;
    }
    template<class T>il print(T x){
    	if(x/10) print(x/10);
    	putchar(x%10+'0');
    }
    ll mul(ll a,ll b,ll mod){long double c=1.;return (a*b-(ll)(c*a*b/mod)*mod)%mod;}
    it qpow(int x,int m,int mod){
    	int res=1,bas=x%mod;
    	while(m){
    		if(m&1) res=(res*bas)%mod;
    		bas=(bas*bas)%mod,m>>=1;
    	}
    	return res%mod;
    }
    const int MAXN = 1e5+5;
    int n,m,val[MAXN];
    double sum[MAXN],a[MAXN],l,r=2000.,eps=1e-5;
    inl bool check(double lim){
    	for(ri i=1;i<=n;++i) a[i]=val[i]-lim,sum[i]=sum[i-1]+a[i];
    	double ans=-1e10,mn=1e10;
    	for(ri i=m;i<=n;++i){
    		mn=min(mn,sum[i-m]);
    		ans=max(ans,sum[i]-mn);
    	}
    	return ans>=0;
    }
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	read(n),read(m);
    	for(ri i=1;i<=n;++i) read(val[i]);
    	while(l+eps<r){
    		if(check(mid)) l=mid;
    		else r=mid;
    	}
    	print(int(r*1000));
    	return 0;
    }
    

    总结

    对于不同的二分的模板一定要记清楚,不然考试打炸了就。。。。

  • 相关阅读:
    欧拉公式
    isap的一些想法
    错误合集
    Hello World
    PAT (Advanced Level) Practice 1068 Find More Coins
    PAT (Advanced Level) 1087 All Roads Lead to Rome
    PAT (Advanced Level) 1075 PAT Judge
    PAT (Advanced Level) 1067 Sort with Swap(0, i)
    PAT (Advanced Level) 1017 Queueing at Bank
    PAT (Advanced Level) 1025 PAT Ranking
  • 原文地址:https://www.cnblogs.com/TheShadow/p/11425959.html
Copyright © 2011-2022 走看看