树状数组,逆序对——CodeForces - 1042D

题目含义

给出一堆数和一个数T

找出满足区间和严格小于T的区间个数

题目分析

又是求区间和,那么就考虑前缀和[a,b]=sum[b]-sum[a-1]<T

如果求出前缀和用两个循环一个个试,那肯定会超时

而式子可以化作 sum[j]-T<sum[i],j>i,这就很像一个求逆序对的问题了

题目代码

#include<stdio.h>
#include<iostream>
#include<math.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=2e5+7;
LL a[maxn],sum[maxn],temp[maxn],c[maxn],t;
int n;
int lowbit(int x){
    return x&(-x);
}
void add(int x){
    while(x<=n+1){
        c[x]++;
        x+=lowbit(x);
    }
}
int ask(int x){
    int ans=0;
    while(x){
        ans+=c[x];
        x-=lowbit(x);
    }
    return ans;
}
int main(){
    scanf("%d%lld",&n,&t);
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        sum[i]=sum[i-1]+a[i];
        temp[i]=sum[i];
    }
    sort(temp,temp+1+n);
    LL ans=0;
    for(int i=1;i<=n;i++){
        int pos=lower_bound(temp,temp+1+n,sum[i-1])-temp+1;
        add(pos);
        pos=upper_bound(temp,temp+1+n,sum[i]-t)-temp;
        ans+=i-ask(pos);
    }
    printf("%lld\n",ans);
    return 0;
}

又因为数组开小了,卡了一会儿。。。

 

posted @ 2019-07-21 21:12  helman78  阅读(163)  评论(0编辑  收藏  举报