CF#510 (Div. 2) D(前缀和,逆序数)
CF#510 Div.2 D. Petya and Array(前缀和,逆序数)
题目链接:http://codeforces.com/contest/1042/problem/D
题目大意:区间中选择一些连续的区间,满足 ,然后看有多少个这样的区间。
思路:满足条件sum[r]-sum[l-1]<t。然后移项得:sum[l-1]>sum[r]-t;因为我们只用枚举sum[l-1],找到符合要求的sum[r],然后这个区间中所有的sum[k](k∈[l,r])都是符合要求的。所以我们只用对sum数组排序,然后对于每个sum[l],求和sum[l-1]之后减去sum[l]即可。因为数据元素比较大且含有负数,所以离散成1~n个数之后在进行查找。
用一个数据结构来维护元素的数量。
两种方法,1.树状数组 2.权值线段树(刚学的)
树状数组ACCode:
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define Pair pair<int,int>
#define M_P(a,b) make_pair(a,b)
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))
//std::ios::sync_with_stdio(false);
// register
const int MAXN=2e5+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double EPS=1.0e-8;
const double PI=acos(-1.0);
int tree[MAXN];
ll a[MAXN],sum[MAXN];
ll n,t,ecnt;
int get_r(ll res){
int l=1,r=ecnt,mid;
while(l<=r){//find the last r to sum[l-1]>sum[r]-t => res>sum[r]
mid=(l+r)>>1;
// cout<<l<<" "<<r<<" => ";
if(res>sum[mid]) l=mid+1;
else r=mid-1;
// cout<<l<<" "<<r<<endl;
}return r;
}
int get_l(ll res){
int l=1,r=ecnt,mid;
while(l<=r){
mid=(l+r)>>1;
if(res==sum[mid]) return mid;
else if(res>sum[mid]) l=mid+1;
else r=mid-1;
}
}
int Lowbit(int i){
return i&(-i);
}
void Updata(int i,int x){
while(i<=n){
tree[i]+=x;
i+=Lowbit(i);
}
}
int Query(int x){
int sum=0;
while(x>0){
sum+=tree[x];
x-=Lowbit(x);
}return sum;
}
int main(){
scanf("%lld%lld",&n,&t);
for(int i=1;i<=n;++i){
scanf("%lld",&a[i]);
sum[i]=sum[i-1]+a[i];
}sort(sum+1,sum+1+n);
for(int i=1;i<=n;++i){
sum[i]=sum[i]-t;
}sort(sum+1,sum+1+n);ecnt=n;
for(int i=1;i<=ecnt;++i){//????? + insert
Updata(i,1);
}
ll ans=0,res=0;
for(int i=1;i<=n;++i){
// now res is sum[l-1]
int r=get_r(res);
// cout<<res<<" : "<<r<<" "<<Query(r)<<" || ";
ans+=Query(r);
res+=a[i];//???????
int l=get_l(res-t);
Updata(l,-1);
}printf("%lld\n",ans);
}
权值线段树ACCode:
// luogu-judger-enable-o2
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<time.h>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define Pair pair<ll,int>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// 水印
//std::ios::sync_with_stdio(false);
// register
const int MAXN=2e5+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double EPS=1.0e-8;
const double PI=acos(-1.0);
ll Tree[MAXN<<2];
ll a[MAXN],sum[MAXN];
ll n,t;
int get_r(ll res){
int l=1,r=n,mid;
while(l<=r){//find the last r to sum[l-1]>sum[r]-t => res>sum[r]
mid=(l+r)>>1;
if(res>sum[mid]) l=mid+1;
else r=mid-1;
}return r;
}
int get_l(ll res){
int l=1,r=n,mid;
while(l<=r){
mid=(l+r)>>1;
if(res==sum[mid]) return mid;
else if(res>sum[mid]) l=mid+1;
else r=mid-1;
}
}
void Update(int l,int r,int x,int oper,int rt){//修改一个点
if(l==r){
Tree[rt]+=oper;
return ;
}int mid=(l+r)>>1;
if(x<=mid) Update(l,mid,x,oper,rt<<1);
else Update(mid+1,r,x,oper,rt<<1|1);
Tree[rt]=Tree[rt<<1]+Tree[rt<<1|1];
}
int Query(int ql,int qr,int l,int r,int rt){
if(qr==0) return 0;
if(l>=ql&&r<=qr){
return Tree[rt];
}int mid=(l+r)>>1;
int ans=0;
if(ql<=mid) ans+=Query(ql,qr,l,mid,rt<<1);
if(qr>mid) ans+=Query(ql,qr,mid+1,r,rt<<1|1);
return ans;
}
int main(){
while(~scanf("%lld%lld",&n,&t)){
clean(Tree,0);
for(int i=1;i<=n;++i){
scanf("%lld",&a[i]);
sum[i]=sum[i-1]+a[i];
}sort(sum+1,sum+1+n);
for(int i=1;i<=n;++i){
sum[i]=sum[i]-t;
}sort(sum+1,sum+1+n);
for(int i=1;i<=n;++i){
Update(1,n,i,1,1);
}ll ans=0,res=0;
for(int i=1;i<=n;++i){
int r=get_r(res);
// cout<<r<<" : ";
ans+=Query(1,r,1,n,1);
// cout<<ans<<" ";
res+=a[i];
int l=get_l(res-t);
Update(1,n,l,-1,1);
}printf("%lld\n",ans);
}
}
/*
*/