[COCI2015-2016#2] VUDU

题目传送门

思路

这是一种简单的树状数组解法。

我们设偏移值表示 \(a_i\) 与目标平均数 \(p\) 的差值,显然,一个区间若能满足条件,需要满足此区间的偏移值之和 \(\ge 0\)

看到区间之和,我们就想到了前缀和,设 \(sum\) 数组表示偏移值的前缀和数组,若我们固定一个右端点 \(r\),则我们要求的是满足 \(sum_r-sum_l \ge 0\)\(l\) 总数,不妨改变一下这个柿子的形式,变成 \(sum_r \ge sum_l\),然后就变成简单的树状数组板子了。

代码

//A tree without skin will surely die. 
//A man without face is invincible.
#include<bits/stdc++.h>
using namespace std;
#define int long long
int const N=1e6+10;
int n,a[N],b[N],sum[N];
struct Tree_Array{
    int c[N];
    #define lowbit(x) (x&-x)
    inline void update(int x,int v){while (x<=n) c[x]+=v,x+=lowbit(x);}
    inline int query(int x){int res=0;while (x) res+=c[x],x-=lowbit(x);return res;}
}T;
signed main(){
    //读入
    for (int i=1;i<=n;++i) a[i]-=p;
    for (int i=1;i<=n;++i) sum[i]=sum[i-1]+a[i],b[i]=sum[i];
    sort(b+1,b+n+1);int l=unique(b+1,b+n+1)-b-1;
    int ans=0;
    for (int i=1;i<=n;++i) ans+=(sum[i]>=0);//这个数本身就满足条件
    for (int i=1;i<=n;++i) sum[i]=lower_bound(b+1,b+l+1,sum[i])-b;//离散化
    for (int i=1;i<=n;++i){
        ans+=T.query(sum[i]);
        T.update(sum[i],1);
    }
    //输出
    return 0;
}
posted @ 2022-10-20 10:15  Tx_Lcy  阅读(28)  评论(0)    收藏  举报