题目描述
佩蒂亚有一个阵列和 �n 个整数。他最近学会了区间和,现在他可以非常快速地计算数组任何区间的元素总和。
现在,他想知道他的数组中总和小于 �t 的区间数量是多少?
更确切地说,你需要计算满足 ��+��+1+⋯+��−1+��<�al+al+1+⋯+ar−1+ar<t 的数对 (l,r) 的数量
输入描述
第一行包含两个整数 �n 和 �t (1≤�≤2×1051≤n≤2×105,∣�∣≤2×1014∣t∣≤2×1014)
第二行包含一个整数序列 �1a1 到 ��an( ∣��∣≤109∣ai∣≤109 ),—对 Petya 数组的描述。请注意,可能存在负元素、零元素和正元素。
输出描述
Petya 数组中的段数,元素之和小于 �t.
输入样例1
5 45 -1 3 4 -1
输出样例1
5
输入样例2
3 0-1 2 -3
输出样例2
4
输入样例3
4 -1-2 1 -2 3
输出样例3
3
代码
#include<bits/stdc++.h>
using namespace std;
long long n,t,a[400005],ans,cnt,c[400005];
vector<long long>v;
int lowbit(int t){ return t&(-t);}
void update (int x,int y){
for(int i=x;i<=2*n+1;i+=lowbit(i)) c[i]+=y;
}
long long getsum (int x){
long long ans=0;
for(int i=x;i;i-=lowbit(i)) ans+=c[i];
return ans;
}
int Find(long long x){
return int(lower_bound(v.begin(),v.end(),x)-v.begin()+1);
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>n>>t;
for(int i=1;i<=n;i++){
cin>>a[i];
a[i]+=a[i-1];
a[n+i]=a[i]+t;
v.push_back(a[i]);
v.push_back(a[n+i]);
}
v.push_back(t);
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
for(int i=1;i<=n*2;i++) a[i]=Find(a[i]);
update(Find(t),1);
cnt=v.size();
for(int i=1;i<=n;i++){
ans+=getsum(cnt)-getsum(a[i]);
//cout<<getsum(cnt)<<endl;
update(a[i+n],1);
}
cout<<ans;
return 0;
}
638

被折叠的 条评论
为什么被折叠?



