第四题 洋娃娃(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; }