[HDU2993]MAX Average Problem

题面描述

传送门

思路

状态转移方程

F i = max ⁡ ( F j , s u m i − s u m j i − j ) F_i=\max(F_j,\frac{sum_i-sum_j}{i-j}) Fi=max(Fj,ijsumisumj)

决策单调性

设有 j &lt; k ≤ i − m j&lt;k\le i-m j<kim

max ⁡ ( F k , s u m i − s u m k i − k ) ≥ max ⁡ ( F j , s u m i − s u m j i − j ) \max(F_k,\frac{sum_i-sum_k}{i-k})\ge \max(F_j,\frac{sum_i-sum_j}{i-j}) max(Fk,iksumisumk)max(Fj,ijsumisumj)

如果

s u m i − s u m k i − k , s u m i − s u m j i − j \frac{sum_i-sum_k}{i-k},\frac{sum_i-sum_j}{i-j} iksumisumk,ijsumisumj

均对答案有贡献,那么

s u m i − s u m k i − k ≥ s u m i − s u m j i − j \frac{sum_i-sum_k}{i-k}\ge \frac{sum_i-sum_j}{i-j} iksumisumkijsumisumj

( s u m i − s u m k ) ∗ ( i − j ) ≥ ( s u m i − s u m j ) ∗ ( i − k ) (sum_i-sum_k)*(i-j)\ge(sum_i-sum_j)*(i-k) (sumisumk)(ij)(sumisumj)(ik)

对于未来状态 t t t,若

s u m t − s u m k t − k , s u m t − s u m j t − j \frac{sum_t-sum_k}{t-k},\frac{sum_t-sum_j}{t-j} tksumtsumk,tjsumtsumj

仍对答案有贡献,

证明

s u m t − s u m k t − k ≥ s u m t − s u m j t − j \frac{sum_t-sum_k}{t-k}\ge\frac{sum_t-sum_j}{t-j} tksumtsumktjsumtsumj

( s u m t − s u m k ) ∗ ( t − j ) ≥ ( s u m t − s u m j ) ∗ ( t − k ) (sum_t-sum_k)*(t-j)\ge(sum_t-sum_j)*(t-k) (sumtsumk)(tj)(sumtsumj)(tk)

s u m k = s u m i + v a l , t − j &gt; t − k sum_k=sum_i+val,t-j&gt;t-k sumk=sumi+val,tj>tk

( s u m i − s u m k ) ∗ ( t − j ) ≥ ( s u m i − s u m j ) ∗ ( t − k ) (sum_i-sum_k)*(t-j)\ge (sum_i-sum_j)*(t-k) (sumisumk)(tj)(sumisumj)(tk)

仅需证明 v a l ∗ ( t − j ) ≥ v a l ∗ ( t − k ) val*(t-j)\ge val*(t-k) val(tj)val(tk)

由于 v a l &gt; 0 val&gt;0 val>0

则成立。

因此 k k k永远优于 j j j

踢队头

c a l c ( k , i ) = s u m i − s u m k i − k ≥ c a l c ( j , i ) = s u m i − s u m j i − j calc(k,i)=\frac{sum_i-sum_k}{i-k}\ge calc(j,i)=\frac{sum_i-sum_j}{i-j} calc(k,i)=iksumisumkcalc(j,i)=ijsumisumj

因此,根据上文

c a l c ( k , i ) ≥ c a l c ( j , i ) calc(k,i)\ge calc(j,i) calc(k,i)calc(j,i)时, k k k优于 j j j

c a l c ( q h e a d + 1 , i ) ≥ c a l c ( q h e a d , i ) calc(q_{head+1},i)\ge calc(q_{head},i) calc(qhead+1,i)calc(qhead,i)时, q h e a d + 1 q_{head+1} qhead+1优于 q h e a d q_{head} qhead

因此观出, c a l c ( q h e a d , i ) calc(q_{head},i) calc(qhead,i) h e a d head head增大而减小,维护一个上凸壳。

踢队尾

c a l c ( i − m , q t a i l − 1 ) ≤ c a l c ( q t a i l , q t a i l − 1 ) calc(i-m,q_{tail-1})\le calc(q_{tail},q_{tail-1}) calc(im,qtail1)calc(qtail,qtail1)

即可。

AC code

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int N=1e5+10;
const int size=1<<20;
inline char gc()
{
	static char buf[size],*p1,*p2;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,size,stdin),p1==p2)?EOF:*p1++;
}
#define gc gc()
inline void qr(int &x)
{
	x=0;int f=1;char c=gc;if(c==EOF)return;
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc;}
	while(c>='0'&&c<='9'){x=x*10+(c^48);c=gc;}x*=f;
}
int s[N];int q[N],l,r;int n,m;
inline double calc(int j,int i)
{
	return (double)(s[i]-s[j])/(i-j);
}
int main()
{
	while(qr(n),n)
	{
		qr(m);
		s[0]=0;
		for(int i=1;i<=n;i++)qr(s[i]),s[i]+=s[i-1];
		l=1;r=0;q[1]=0;double ans=0;
		for(int i=m;i<=n;i++)
		{
			while(l<r&&calc(q[r],q[r-1])>=calc(i-m,q[r-1]))--r;
			q[++r]=i-m;
			while(l<r&&calc(q[l+1],i)>=calc(q[l],i))++l;
			ans=max(ans,calc(q[l],i));
		}
		printf("%.2lf\n",ans);
	}
	return 0; 
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值