suoi07 区间平均++ (二分答案+前缀和)
https://www.vijos.org/d/SUOI/p/59dc5af7d3d8a1361ae62b97
二分一个答案,然后做一做前缀和,用满足区间大小的最小值减一减,判断答案合不合法
然而还要输出一个最小的区间 太毒瘤了
但其实最后答案中最小区间的端点就只能是刚才做的那个最小值,因为如果不是最小值,那这个答案一定不是最优的
然后再随便对比一下就完事了
(感觉什么都没说清,看代码吧代码好看代码也不好看)
1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define ll long long 4 using namespace std; 5 const int maxn=1e6+5; 6 7 inline ll rd(){ 8 ll x=0;char c=getchar();int neg=1; 9 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 10 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 11 return x*neg; 12 } 13 14 int N,K,Ma,Mi,num[maxn]; 15 double sum[maxn]; 16 17 inline bool judge(int &x,int &y,double r){ 18 int a=-1,b=N+1; 19 for(int i=1;i<=N;i++) sum[i]=sum[i-1]+num[i]-r; 20 double mi=1e9;int mn;bool re=0; 21 for(int i=K;i<=N;i++){ 22 if(mi>=sum[i-K]) mi=sum[i-K],mn=i-K; 23 if(sum[i]>=mi){ 24 re=1;if(b-a>i-mn||(b-a==i-mn&&mn<a)) a=mn,b=i; 25 } 26 }if(re) x=a+1,y=b; 27 return re; 28 } 29 30 int main(){ 31 int i,j,k; 32 N=rd();K=rd();Ma=-10000;Mi=10000; 33 for(i=1;i<=N;i++) num[i]=rd(),Ma=max(num[i],Ma),Mi=min(num[i],Mi); 34 double l=Mi-1,r=Ma+1;int a,b; 35 while(l<=r-1e-7){ 36 double m=(l+r)/2; 37 if(judge(a,b,m)) l=m+1e-6; 38 else r=m-1e-6; 39 }printf("%d %d %.4f",a,b,l); 40 return 0; 41 }