树状数组,逆序对——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; }
又因为数组开小了,卡了一会儿。。。