题意:
求第K 大连续区间
分析:
二分答案,再n * log(n)判断有几个区间的区间和大于mid,然后调整上下界,使这个值不断的接近k。
判断符合条件的区间总数:线性扫描sum[n](前n项和) 每次判断以i结尾的区间有几个区间和大于等于mid,累加即可
// File Name: 191-E.cpp // Author: Zlbing // Created Time: 2013年08月03日 星期六 15时10分13秒 #include<iostream> #include<string> #include<algorithm> #include<cstdlib> #include<cstdio> #include<set> #include<map> #include<vector> #include<cstring> #include<stack> #include<cmath> #include<queue> using namespace std; #define CL(x,v); memset(x,v,sizeof(x)); #define INF 0x3f3f3f3f #define LL long long #define REP(i,r,n) for(int i=r;i<=n;i++) #define RREP(i,n,r) for(int i=n;i>=r;i--) const int MAXN=1e5+100; int tree[MAXN]; int n; int lowbit(int x) { return x&(-x); } void add(int pos,int val) { while(pos<=n) { tree[pos]+=val; pos+=lowbit(pos); } } int read(int x) { int s=0; while(x>0) { s+=tree[x]; x-=lowbit(x); } return s; } LL sum[MAXN]; LL num[MAXN]; int N; LL M; LL solve(LL mid) { CL(tree,0); LL ans=0; for(int i=1;i<=N;i++) { if(sum[i]>=mid)ans++; LL t=sum[i]-mid; int a=upper_bound(num+1,num+n+1,t)-num-1; int b=lower_bound(num+1,num+n+1,sum[i])-num; ans+=read(a); add(b,1); } //cout<<"ans="<<ans<<endl; return ans; } int main() { while(~scanf("%d%lld",&N,&M)) { sum[0]=0; LL l,r; REP(i,1,N) { scanf("%lld",&sum[i]); sum[i]+=sum[i-1]; num[i]=sum[i]; } sort(num+1,num+N+1); n=unique(num+1,num+N+1)-num-1; //cout<<"l="<<l<<"r="<<r<<endl; LL best=-1; l=-1e18; r=1e18; while(l<=r) { LL mid=l+(r-l+1)/2; //cout<<"l="<<l<<"r="<<r<<"mid="<<mid<<endl; if(solve(mid)>=M) { best=mid; l=mid+1; } else r=mid-1; } cout<<best<<endl; } return 0; }