好题*1

题意:给定一个长为n的序列,求序列上任取一段非空子区间,其区间内的数的平均值在L~R之间的期望。(n<=5e5,区间数的权值及l,r均在100以内)

做法:显然是计数问题,先推一波式子,对序列做前缀和后所求变为:

求满足L(r-l+1)<=sum[r]-sum[l-1]<=R(r-l+1) 的l,r对数

移项化简,得到所求变为:sum[l-1]-(l-1)R>=sum[r]-r*R,sum[l-1]-(l-1)L<=sum[r]-r*L。

做到这一步我们可以发现,可以对位置i维护两个值f[i],g[i],

f[i]=sum[i]-i*L,g[i]=sum[i]-i*R.

所求变为:

求满足i>j,且f[i]>=f[j],且g[i]<=g[j]的i,j对数。

这不是裸的三维偏序吗,可是你会发现这题数据范围5e5,(忘说了时限1s),nlog^2n跑不过的...

但我们可以发现,直接这样化简损失了一些f数组和g数组之间的关系:

g[i]=f[i]-(R-L)*i

假设两位置i,j(i>j)其f[i]<f[j](即不满足f[i]>=f[j])

那么带入我们忽略的f,g关系可得:

g[i]=f[i]-(R-L)i

g[j]=f(j)-(R-L)j

而f[i]<f[j]  i>j R>=L

所以此时g[i]<g[j] !!!

同理可推g[i]>g[j]。

所以发现不满足f性质的一定满足g性质,不满足g性质的一定满足f性质。

所以只要算每个位置的贡献减去不满足f性质的和不满足g性质的即可,变成一个二维偏序,直接树状数组。。

(注意下最早的原式中是l-1~r,所以处理的时候要把0放入)。

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=5e5+10;

void read(int &x)
{
	char c=getchar();x=0;bool f=0;
	while(!isdigit(c))f|=(c=='-'),c=getchar();
	while(isdigit(c))x=x*10+c-48,c=getchar();
	if(f)x=-x;
}

int a[N],sum[N],n,f[N],g[N],tax[N],L,R;
ll ans=0;
struct BIT{
	int tr[N];
	int ask(int x)
	{
		int res=0;
		for(;x;x-=x&-x)res+=tr[x];
		return res;
	}
	void add(int x)
	{for(;x<=n+5;x+=x&-x)tr[x]++;}
	int ask(int l,int r)
	{return ask(r)-ask(l-1);}
}t1,t2;
ll gcd(ll x,ll y)
{return !y?x:gcd(y,x%y);}
int main()
{
	read(n),read(L),read(R);
	for(int i=1;i<=n;i++)
		read(a[i]);
	for(int i=1;i<=n;i++)
		sum[i]=sum[i-1]+a[i];
	for(int i=0;i<=n;i++)
		f[i]=sum[i]-i*L,g[i]=sum[i]-i*R,tax[i]=f[i];
	sort(tax,tax+n+1);
	int len=unique(tax,tax+n+1)-tax;
	for(int i=0;i<=n;i++)
		f[i]=1+lower_bound(tax,tax+len+1,f[i])-tax;
	for(int i=0;i<=n;i++)
		tax[i]=g[i];
	sort(tax,tax+n+1);
	len=unique(tax,tax+n+1)-tax;
	for(int i=0;i<=n;i++)
		g[i]=1+lower_bound(tax,tax+len+1,g[i])-tax;
	for(int i=0;i<=n;i++)
	{
		if(i!=0)ans+=i-t1.ask(f[i]+1,n+5)-t2.ask(g[i]-1);
		t1.add(f[i]),t2.add(g[i]);
	}
	ll tot,L;
	tot=1LL*n*(n+1)/2LL;
	L=gcd(ans,tot);
	ans/=L,tot/=L;
	if(ans==0)return puts("0"),0;
	if(ans==tot)return puts("1"),0;
	printf("%lld/%lld",ans,tot);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值