洋娃娃

第四题 洋娃娃(yww)

【问题描述】
洋洋最近一直在买洋娃娃。她一直对尽可能便宜的购买感兴趣,她每一天都在跟踪洋娃
娃的价格,她的价格清单包括过去 N 天洋娃娃的价格,Ai 代表第 i 天洋娃娃的价格,洋洋
认为通过研究连续几天娃娃价格的平均数可以预测以后的娃娃价格。
现在洋洋想让你帮忙找出:
“对于给定的 P,过去的 N 天有多少个不同的连续子序列的
平均值大于或者等于 P” 两个连续子序列被认为是不同的,当且仅当它们开始或者结束时
位置不同的。
【输入格式】
第一行为一个整数 N(1<=N<=1000,000),表示序列长度。
第二行为 N 天的价格 ai(0<=ai<=1,000,000,000)。
第三行包为一个整数 P(0<=P<=1,000,000,000)。
【输出格式】
输出为一个整数,即答案。
【输入输出样例】
样例解释:
对于样例 1,平均值大于等于 3 的为 1 个{3}。
对于样例 2,平均值大于等于 2 的为 5 个{1,3},{1,3,2},{3},{3,2},{2}。

 

将所有的a[i]-=x后的前缀和sum[i]求出来,题目转化成有多少个区间[l,r]内数字和>=0
即sum[r]-sum[l-1]>=0,即统计l-1<r且sum[l-1]<=sum[r]的数对(l-1,r)的数量
归并排序、树状数组或线段树统计顺序对(或逆序对)个数即可
由于sum[i]的值会比较大,需要离散化
时间复杂度O(NlogN)

 

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <map>
#define MAXN 1000005
#define R register
#define LL long long
using namespace std;
int n,c[MAXN],p;LL a[MAXN];
struct node {LL r;int s;}al[MAXN];
inline bool cmp(node x,node y)
{
    if(x.r!=y.r) return x.r<y.r;
    return  x.s<y.s;
}
inline int lowbit(int x) {return x&-x;}
inline void add(int x)
{
    x++;
    for(;x<MAXN;x+=lowbit(x)) c[x]++;
}
inline int sum(int x)
{
    int ans=0;x++;
    for(;x;x-=lowbit(x)) ans+=c[x];
    return ans;
}
int main()
{
    freopen("yww.in","r",stdin);
    freopen("yww.out","w",stdout);
    cin>>n;
    for(R int i=1;i<=n;i++) cin>>a[i];
    cin>>p;
    for(R int i=1;i<=n;i++) a[i]+=a[i-1]-p,al[i]=(node){a[i],i};
    sort(al,al+1+n,cmp);
    LL ans=0;
    for(R int i=0;i<=n;i++) ans+=sum(al[i].s),add(al[i].s);
    cout<<ans<<endl;
    return 0;
}

 

转载于:https://www.cnblogs.com/000226wrp/p/11336319.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值