题目链接:D. Petya and Array
题意
寻找有多少这样的区间[l,r]使得 a l + a l + 1 + . . . + a r < t {a_l+a_{l+1}+...+a{r}<t} al+al+1+...+ar<t
代码
归并解法
const int N=2e5+100;
int n;
LL sum[N];
LL ans=0;
LL t;
void Solve(int l,int r) {
if(l>=r)return;
int mid=(l+r)>>1;
Solve(l,mid);
Solve(mid+1,r);
LL ret=0;
for(int i=l,j=mid+1;i<=mid;++i)
{
while(j<=r&&sum[j]-sum[i]<t) j++;
ret+=j-mid-1;
}
ans+=ret;
inplace_merge(sum+l,sum+mid+1,sum+r+1);
}
int main()
{
cin>>n>>t;
for(int i=1;i<=n;++i)
{
cin>>sum[i];
sum[i]+=sum[i-1];
}
Solve(0,n);
cout<<ans;
}
权值线段树解法
树状数组解法
#define lowbit(x) x&-x
ll n,t,c[maxn],su[maxn];
void add(int x,ll d)
{
while (x<=n+1) { c[x]+=d; x+=lowbit(x); }
}
ll sum(int x)
{
ll ans=0;
while (x>0) { ans+=c[x]; x-=lowbit(x); }
return ans;
}
ll a[maxn],cnt[maxn];
int main()
{
scanf("%lld%lld",&n,&t);
for(int i=2;i<=n+1;i++)
{
scanf("%lld",&a[i]);
su[i]=su[i-1]+a[i];
cnt[i]=su[i];
}
sort(cnt+1,cnt+n+2);
ll ans=0;
for(int i=1;i<=n+1;i++)
{
int x=upper_bound(cnt+1, cnt+n+2, su[i]-t)-cnt;
ans+=sum(n+1)-sum(x-1);
x=lower_bound(cnt+1, cnt+n+2, su[i])-cnt;
add(x, 1);
}
printf("%lld",ans);
}