P7795 [COCI2014-2015#7] PROSJEK

有一个由 \(n\) 个整数组成的数列 \(a\) 。请求出所有长度不少于 \(k\) 的子串的平均值最大为多少,保留三位小数。

注意:某一子串的平均值为子串中所有数的和除以子串的长度。

\(1\leq n\leq 3\cdot 10^5,1\leq k\leq n,1\leq a_i\leq 10^6\)

如果枚举子串的大小的话,时间复杂度无法做到 \(O(\log n)\) 或者 \(O(\log^2 n)\) .

因为是平均值,可以考虑二分,二分平均值的大小 .

这里可以直接二分小数,或者乘以 \(10000\) . 我选择后一种 .

那么,对于当前 \(mid\) ,枚举子串的右端点 \(r\) ,那么左端点 \(l\) 满足 \(r-k+1\geq l\) ,且 \(\frac{\sum\limits_{i=l}^{r} a_i}{r-l+1}\geq mid\) ,就存在一组满足条件的解 .

\[\frac{\sum\limits_{i=l}^{r} a_i}{r-l+1}\geq mid\ \longrightarrow\ \sum\limits_{i=l}^{r}a_i\geq mid(r-l+1)\ \longrightarrow\ \sum\limits_{i=l}^{r}a_i-mid(r-l+1)\geq 0\ \longrightarrow\ \sum\limits_{i=l}^{r}(a_i-mid)\geq 0 \]

此时,这是一个以 \(r\) 结尾的后缀和,可以直接 \(O(n)\) 地解决 .

这里还有一个问题,就是在我写的时候,发现比如说 \(0.755\) 不管是 printf(".3f") 还是 fixed setprecision 都不会进位到 \(0.76\) ,但是对于 \(0.7555\) 就会,我感到很迷惑.

时间复杂度 : \(O(n\log 10000a_i)\)

空间复杂度 : \(O(n)\)

#include<bits/stdc++.h>
using namespace std;
const long long inf=1e18+10;
int n,k;
long long a[300010],sum[300010];
inline int read(){
	char ch=getchar();
	while(ch<‘0‘||ch>‘9‘)ch=getchar();
	int res=0;
	while(ch>=‘0‘&&ch<=‘9‘){
		res=res*10+ch-‘0‘;
		ch=getchar();
	}
	return res;
}
bool check(long long x){
	for(int i=0;i<n;i++)sum[i]=a[i]-x;
	for(int i=1;i<n;i++)sum[i]+=sum[i-1];
	long long mx=-inf;
	for(int i=0;i<n;i++){
		if(mx!=-inf)mx+=a[i]-x;
		if(i+1>=k)mx=max(mx,sum[i]-(i-k>=0?sum[i-k]:0));
		if(mx>=0)return true;
	}
	return false;
}
int main(){
//	freopen("test.txt","r",stdin);
	n=read();k=read();
	for(int i=0;i<n;i++)a[i]=read();
	for(int i=0;i<n;i++)a[i]*=10000ll;
	long long mx=a[0];
	for(int i=1;i<n;i++)mx=max(mx,a[i]);
	long long low=0,high=mx+1,ans=0;
	while(low<high){
		long long mid=(low+high)>>1;
		if(check(mid)){
			ans=max(ans,mid);
			low=mid+1;
		}
		else{
			high=mid;
		}
	}
	printf("%lld",ans/10000);
	int tmp=ans%10,res=ans%10000/10;
	if(tmp%10>=5)res++;
	printf(".");
	vector<int>v;
	for(int i=0;i<3;i++){
		v.push_back(res%10);
		res/=10;
	}
	for(int i=2;i>=0;i--)printf("%d",v[i]);
	printf("\n");
	return 0;
}
/*inline? ll or int? size? min max?*/

P7795 [COCI2014-2015#7] PROSJEK

上一篇:基于C# Winform的简易聊天程序[第一篇-两端通信]


下一篇:每周学习总结(七)