AtCoder Regular Contest 075 E - Meaningful Mean(树状数组)

题目链接

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
Copy
3 6
7
5
7
Sample Output 1
Copy
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
Copy
1 2
1
Sample Output 2
Copy
0
Sample Input 3
Copy
7 26
10
20
30
40
30
20
10
Sample Output 3
Copy
13

题意:给出 \(N(1 \leq N \leq 2 \times 10^5)\) 个数和 \(K\)\(1 \leq a[i] \leq 10^9\),求多少个连续区间使得他们的平均值大于等于 \(K\).

题解:
每个数减去 \(K\),然后求前缀和 \(sum[i]\),那么就是对每个 \(i\) 求有多少个 \(j\) 使得 \(sum[j-1]<=sum[i]\),将 \(sum\) 数组进行离散化,用 "权值树状数组" 即可。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define fi first
#define se second
#define dbg(...) cerr<<"["<<#__VA_ARGS__":"<<(__VA_ARGS__)<<"]"<<endl;
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn=2e5+100;
ll sum[maxn];
int c[maxn];
int cnt=0;
void add(int x)
{
    while(x<=cnt)
    {
        c[x]++;
        x+=x&(-x);
    }
}
int get_sum(int x)
{
    int ans=0;
    while(x)
    {
        ans+=c[x];
        x-=x&(-x);
    }
    return ans;
}
ll h[maxn];
int v[maxn];
int main()
{
    int n,k;
    scanf("%d%d",&n,&k);
    rep(i,1,n+1) scanf("%lld",&sum[i]),sum[i]-=1ll*k;
    rep(i,1,n+1) sum[i]=sum[i-1]+sum[i],h[i]=sum[i];
    sort(h+1,h+n+1);
    cnt=unique(h+1,h+n+1)-h-1;
    ll ans=0;
    rep(i,1,n+1)
    {
        int pos=lower_bound(h+1,h+cnt+1,sum[i])-h;
        if(sum[i]>=0) ans++; //此时是[1,i]全选
        ans+=get_sum(pos);
        add(pos);
    }
    printf("%lld\n",ans);
    return 0;
}
posted @ 2017-09-23 21:19  tarjan's  阅读(119)  评论(0编辑  收藏  举报