【codevs3324】新斯洛克

本着快noip了,要复习一下基础算法的原则,去找了到分治的题目……结果……这题真是……好吧确实算是分治……
这题灰常巧妙,n^2贼好想,但是怎么压成nlogn就挺有难度的……不看题解真心想不到居然还可以这么玩……
因为他说求平均数大于m的所有区间,也就是说,如果把每个数都减去m,其区间和大于0的就是我们要找的区间之一,所以先预处理一下,把每一个数先减去m,求前缀和,如果s[r]-s[l-1]大于0就ans++,但是这样明显n^2,所以我们需要更高效的找满足i<=j&&s[j]-s[i-1]>0,这个性质是不是很像逆序对呢,所以可以归并排序nlogn找(我第一次看到这种想法也是懵逼了,城里人真会玩qwq)
记得排序从0开始,不然会错

#include<iostream>
#include<cstdio>
using namespace std;
long long ans;
int n,m,qwq[100010],su[100010],cun[100010];
inline void m_st(int l,int r)
{
    if(l>=r)
        return;
    int mid=l+r>>1,t1=l,t2=mid+1,t3=l-1;
    m_st(l,mid),m_st(mid+1,r);
    while(t1<=mid&&t2<=r)
    {
        if(su[t1]<su[t2])
            cun[++t3]=su[t1++],ans+=r-t2+1;
        else
            cun[++t3]=su[t2++];
    }
    while(t1<=mid)
        cun[++t3]=su[t1++];
    while(t2<=r)
        cun[++t3]=su[t2++];
    for(int i=l;i<=r;i++)
        su[i]=cun[i];
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&qwq[i]),qwq[i]-=m,su[i]=su[i-1]+qwq[i];
    m_st(0,n);
    cout<<ans; 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值