3 solutions

  • 1
    @ 2022-3-4 9:40:13

    和老钟方法一样

    #include<bits/stdc++.h>
    using namespace std;
    int n,L;
    double ans,i[100005],p[100005],j[100005],k[100005];
    int main()
    {
    	scanf("%d%d",&n,&L);
    	double l=0,r=2000,jin=1e-6,mid;
    	for(int c=0;c<n;c++) scanf("%lf",&i[c]);
    	while(r-l>jin){
    		mid=(l+r)/2;
    		for(int c=0;c<n;c++){
    			p[c]=i[c]-mid;
    			if(c){
    				k[c]=max(k[c-1]+p[c],p[c]);
    				j[c]=j[c-1]+p[c];
    			}else{
    				j[c]=k[c]=p[c];
    			}
    		}
    		ans=j[L-1];
    		for(int c=L;c<n;c++){
    			double ans1=j[c]-j[c-L+1]+k[c-L+1];
    			ans=max(ans,ans1);
    		}
    		ans>=0?l=mid:r=mid;
    	}
    	printf("%d",(int)(r*1000));
    }
    • 0
      @ 2022-6-6 21:43:04

      难以言喻的一题,再一次感觉到了我的愚蠢

      #include<iostream>
      using namespace std;
      #define MAX 100007
      #define INF 0x3f3f3f3f
      
      double l=1e5+7,r=0;
      int n,f;
      int a[MAX],s[MAX];
      
      bool check(double ave){
      	double sum1=s[f-1]-ave*(f-1);
      	for(int i=f;i<=n;i++){
      		double sum2=s[i]-s[i-f]-ave*f;
      		sum1=sum1+a[i]-ave;
      		sum1=max(sum1,sum2);
      		if(sum1>-1e-5)return false;
      	}
      	return true;
      }
      
      double search(double L,double R){
      	double mid;
      	while(R-L>=1e-5){
      		mid=(L+R)/2;
      		if(check(mid))R=mid;
      		else L=mid;
      	}
      	return R;
      }
      
      int main(){
      	ios::sync_with_stdio(false);
      	cin>>n>>f;
      	for(int i=1;i<=n;i++){
      		cin>>a[i];
      		if(a[i]>r)r=a[i];
      		if(a[i]<l)l=a[i];
      		s[i]=s[i-1]+a[i]; 
      	}
      	
      	double ans=search(l,r);
      	cout<<(int)(ans*1000);
      	return 0;
      }
      
      • 0
        @ 2022-1-5 20:00:20

        https://blog.csdn.net/justidle/article/details/104318076

        #include <bits/stdc++.h>
        using namespace std;
         
        const int MAXN = 1e5+2;
        double data[MAXN] = {};//保存数组A
        double a[MAXN];//减去枚举值后的数组
        double sum[MAXN];//前缀和数组
        double maxx[MAXN];// i 为结尾的最大连续区间和
        double dp[MAXN];// i 为结尾区间连续长度大于等于 L 的最大连续区间和
         
        int main() {
            //读入n和l
            int n,l;
            scanf("%d%d", &n, &l);
            //读入数组A
            int i;
            double left = 2000;//左边界
            double right = 1;//右边界
            for (i=1; i<=n; i++) {
                //注意由于需要使用前缀和,所以第一个数据要设置为0
                scanf("%lf", &data[i]);
                left = min(left, data[i]);//更新左边界
                right = max(right, data[i]);//更新右边界
            }
         
            double eps = 1e-6;//精度
            while (right-left > eps) {
                //计算中间值
                double mid = (left+right)/2;
         
                //数组A的每个数据减去这个枚举值,并计算前缀和
                for (i=1; i<=n; i++) {
                    a[i]=data[i]-mid;
                    sum[i]=sum[i-1]+a[i];
                    maxx[i] = max(a[i], maxx[i-1]+a[i]);
                }
         
                //遍历长度为L到n所有子序列
                double ans=sum[l];
                for (i=l+1; i<=n; i++) {
                    dp[i]=maxx[i-l+1]+sum[i]-sum[i-l+1];
                    if (ans<dp[i]) {
                        ans=dp[i];
                    }
                }
         
                //修正边界
                if (ans>=0) {
                    left = mid;
                } else {
                    right = mid;
                }
            }
         
            //输出
            printf("%d\n", (int)(right*1000));
         
            return 0;
        }
        
        • 1

        Information

        ID
        167
        Time
        1000ms
        Memory
        256MiB
        Difficulty
        7
        Tags
        # Submissions
        42
        Accepted
        12
        Uploaded By