[ARC075E] Meaningful Mean

[ARC075E] Meaningful Mean

好题。

首先显然有一个暴力做法,也就是 O(n2)O(n^2) 的,考虑暴力枚举每一个区间,查询区间和显然可以考虑预处理前缀和。判断一下这个和是否大于等于 kk 即可。

核心的一行是:

if(s[i]-s[j-1]>=k*(i-j+1))

然后考虑把这个式子拆开。

k×ik×(j1)sisj1k \times i-k \times(j-1)\le s_i-s_{j-1} sj1k×(j1)sik×is_{j-1}-k\times (j-1)\le s_i-k \times i

显然我们可以预处理 1in1\le i\le n 的所有 ii,所以就变成了在 1j<i1\le j < i 中找小于等于 sik×is_i -k\times i 的值。显然可以用一个树状数组去维护,类似于求逆序对,开一个值域大小的树状数组,按照逆序对的求法来就好了。

注意,当 j=1j=1 时,j1j-100,在 1in1\le i\le n 的预处理中是处理不到的,所以我们要把第一个位置留出来给 00,后面整体挪一个位置即可。

#include<bits/stdc++.h>
using namespace std;
const int N =1e6+10;
#define int long long	
int n,k;
struct node
{
	int val,num;
}a[N];
bool cmp(node a,node b)
{
	if(a.val==b.val)
		return a.num<b.num;
	return a.val<b.val;
}
int ranks[N],c[N],s[N];
int lowbit(int x)
{
	return x&-x;
}
void update(int x,int change)
{
	for(int i=x;i<=n+1;i+=lowbit(i))
		c[i]+=change;
}
int Query(int x)
{
	int sum=0;
	for(int i=x;i>0;i-=lowbit(i))
		sum+=c[i];
	return sum;
}
signed main()
{
	cin>>n>>k;
	for(int i=1,x;i<=n;i++)
		cin>>x,s[i]=s[i-1]+x;
	a[1].val=0,a[1].num=1;
	for(int i=2;i<=n+1;i++)
		a[i].val=s[i-1]-k*(i-1),a[i].num=i;
	sort(a+1,a+n+2,cmp);
	for(int i=0;i<=n+1;i++)	
		ranks[a[i].num]=i;
	int ans=0;
	for(int i=1;i<=n+1;i++)
		ans+=Query(ranks[i]),update(ranks[i],1);
	cout<<ans<<endl;
	return 0;
}
posted @   June_Failure  阅读(7)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示