E - Meaningful Mean
Time limit : 2sec / Memory limit : 256MB
Score : 600 points
Problem Statement
You are given an integer sequence of length N, a= {a1,a2,…,aN}, and an integer K.
a has N(N+1)⁄2 non-empty contiguous subsequences, {al,al+1,…,ar} (1≤l≤r≤N). Among them, how many have an arithmetic mean that is greater than or equal to K?
Constraints
- All input values are integers.
- 1≤N≤2×105
- 1≤K≤109
- 1≤ai≤109
Input
Input is given from Standard Input in the following format:
N K a1 a2 : aN
Output
Print the number of the non-empty contiguous subsequences with an arithmetic mean that is greater than or equal to K.
Sample Input 1
3 6 7 5 7
Sample Output 1
5
All the non-empty contiguous subsequences of a are listed below:
- {a1} = {7}
- {a1,a2} = {7,5}
- {a1,a2,a3} = {7,5,7}
- {a2} = {5}
- {a2,a3} = {5,7}
- {a3} = {7}
Their means are 7, 6, 19⁄3, 5, 6 and 7, respectively, and five among them are 6 or greater. Note that {a1} and {a3} are indistinguishable by the values of their elements, but we count them individually.
Sample Input 2
1 2 1
Sample Output 2
0
Sample Input 3
7 26 10 20 30 40 30 20 10
Sample Output 3
13
题意:给出一个N个数的序列A,问有多少个区间的平均数大于等于P;
思路:每个数都减去平均数,然后对每个数求前i项和;对前n项和,进行离散化,然后利用树状数组求出对于每个i,前面有多少个数字比它小,然后累加;不过要注意对前n项和遍历一遍,遇到值大于等于0的值ans+1;
样例: 7 5 4 6 8
利用树状数组求的是: 对于5 : 区间(5,5);
对于4 : 区间(5,4)、(4,4)
对于6 : 区间(5,6)、(4,6)、(6,6)
对于8 : 区间(5,8)、(4,8)、(6,8)的区间和是否大于0(各数已经减过p了);
遍历前n项和求的是:(7,7),(7,5),(7,4),(7,6),(7,8)各区间的和是够大于0(各数已经减过p了);
这样就把所有的区间都给处理到了;
样例:
3 6
7 5 7
-k: 1 -1 1
sum: 1 0 1
离散: 2 1 3
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=200005;
typedef long long ll;
struct node
{
ll index,value;
}a[maxn];
ll C[maxn],n,k;
//离散化排序;
int cmp1(node a,node b)
{
if(a.value!=b.value)
return a.value<b.value;
return a.index<b.index;
}
int cmp2(node a,node b)
{
if(a.index!=b.index)
return a.index<b.index;
return a.value<b.value;
}
ll lowbit(ll x)
{
return x&(-x);
}
void add(ll x,ll d)
{
while(x<maxn)
{
C[x]+=d;
x+=lowbit(x);
}
}
ll sum(ll x)
{
ll ret=0;
while(x>0)
{
ret+=C[x];
x-=lowbit(x);
}
return ret;
}
int main()
{
ll ans=0;
scanf("%lld%lld",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i].value);
a[i].index=i;
a[i].value-=k;
}
for(int i=2;i<=n;i++)
a[i].value=a[i-1].value+a[i].value;
for(int i=1;i<=n;i++)
if(a[i].value>=0)
ans+=1;
//printf("%d\n",ans);
sort(a+1,a+1+n,cmp1);
for(int i=1;i<=n;i++)
a[i].value=i;
sort(a+1,a+1+n,cmp2);
//for(int i=1;i<=n;i++)
// printf("%d ",a[i].value);
// printf("\n");
for(int i=1;i<=n;i++)
{
ll x=a[i].value;
ans+=sum(x);
add(x,1);
}
printf("%lld\n",ans);
return 0;
}