codeforces 191 E 数据结构题

题意,给你n个数,让你求第k大的连续区间和是多少

例如

3 4

1 4 2

最大的区间和 1 4 2

第二大         4 2

第三大         1 4

第四大即答案 4

首先要看出单调性:枚举的和越大,区间和大于它的区间数就越少

所以可以采用二分+树状数组统计的方法

二分答案,再n * log(n)判断有几个区间的区间和大于mid,然后调整上下界,使这个值不断的接近k。

判断符合条件的区间总数:线性扫描s【】(前n项和)  每次判断以i结尾的区间有几个区间和大于等于mid,累加即可

View Code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define clr(x,what) memset(x,what,sizeof(x));
typedef __int64 lld;
const int maxn = 100010;
const lld inf = 1e9 ;
int c[maxn];
lld s[maxn],num[maxn];
int n,tot;
void update(int x,int d){
    for(;x<maxn;x+=x&-x)
        c[x]+=d;
}
int sum(int x){
    int ans=0;
    for(;x>0;x-=x&-x)
        ans+=c[x];
    return ans;
}
lld calc(lld mid){
    lld ans=0;
    clr(c,0);
    for(int i=1;i<=n;i++){
        if(s[i]>=mid) ans++;
        lld x=s[i]-mid;
        int id=upper_bound(num+1,num+tot+1,x)-num-1;
        int id2=lower_bound(num+1,num+tot+1,s[i])-num;
        ans+=sum(id);
        update(id2,1);
    }
    return ans;
}
int main(){
    int i,j,k;
    lld m;
    scanf("%d%I64d",&n,&m);
    for(i=1;i<=n;i++){
        scanf("%I64d",&s[i]);
        s[i]+=s[i-1];
        num[i]=s[i];
    }
    sort(num+1,num+n+1);
    tot=unique(num+1,num+n+1)-num-1;
    lld l=-inf*lld(n),r=inf*lld(n),mid,best=-1;
    while(l<=r){
        mid=(l+r)/2;
        if(calc(mid)>=m){
            best=mid;
            l=mid+1;
        }
        else r=mid-1;
    }
    printf("%I64d\n",best);
    return 0;
}

 

copy了“红”牛的平衡树代码

View Code
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
using namespace std;

#define lowbit(x) ((x)&(-(x)))
#define sqr(x) ((x)*(x))
#define PB push_back
#define MP make_pair

typedef unsigned long long ULL;
typedef long long LL;
typedef vector<int> VI;
typedef vector<string> VS;
typedef pair<int,int> PII;

struct Tpoint
{
    double x,y;
    Tpoint(){}
    Tpoint(double _x,double _y){x=_x;y=_y;}
    inline void read(){scanf("%lf%lf",&x,&y);}
    inline void show(){printf("%lf %lf\n",x,y);}
    inline double norm(){ return sqrt( sqr(x)+sqr(y) ); }
};

inline Tpoint operator +(const Tpoint &a,const Tpoint &b){ return Tpoint(a.x+b.x,a.y+b.y); }
inline Tpoint operator -(const Tpoint &a,const Tpoint &b){ return Tpoint(a.x-b.x,a.y-b.y); }
inline Tpoint operator *(const Tpoint &a,const double &b){ return Tpoint(a.x*b,a.y*b); }
inline Tpoint operator /(const Tpoint &a,const double &b){ return Tpoint(a.x/b,a.y/b); }
inline double det(const Tpoint &a,const Tpoint &b){ return a.x*b.y-a.y*b.x; }
inline double dot(const Tpoint &a,const Tpoint &b){ return a.x*b.x+a.y*b.y; }
//=============================================================================================
const int maxn      =   100005;
const long long inf =   1000000000000000LL;
struct node
{
    int left,right,aux,cnt,size;
    long long key;
}tree[maxn];
int n,a[maxn],tot;
long long s[maxn];
inline void init()
{
    tot=0;
    tree[0].left=tree[0].right=tree[0].cnt=tree[0].size=0;
    tree[0].aux=(RAND_MAX<<14)+RAND_MAX+1;
}
inline void renew(int &root)
{
    tree[root].size=tree[root].cnt+tree[tree[root].left].size+tree[tree[root].right].size;
}
inline void leftRotate(int &root)
{
    int t=tree[root].left;
    tree[root].left=tree[t].right;
    tree[t].right=root;
    renew(root);
    renew(t);
    root=t;
}

inline void rightRotate(int &root)
{
    int t=tree[root].right;
    tree[root].right=tree[t].left;
    tree[t].left=root;
    renew(root);
    renew(t);
    root=t;
}
inline void insert(int &root,long long key)
{
    if (root==0){
        root=++tot;
        tree[root].left=tree[root].right=0;
        tree[root].cnt=tree[root].size=1;
        tree[root].key=key;
        tree[root].aux=(rand()<<14)+rand();
        return;
    }
    if (tree[root].key==key){
        ++tree[root].cnt;
    }else if (key<tree[root].key){
        insert(tree[root].left,key);
        if (tree[tree[root].left].aux<tree[root].aux) leftRotate(root);
    }else{
        insert(tree[root].right,key);
        if (tree[tree[root].right].aux<tree[root].aux) rightRotate(root);
    }
    renew(root);
}
inline int getNum(int &root,long long key)
{
    if (root==0) return 0;
    if (tree[root].key>key) return getNum(tree[root].left,key);
    return tree[root].cnt+tree[tree[root].left].size+getNum(tree[root].right,key);
}
inline long long calc(long long limit)
{
    init();
    int root=0;
    insert(root,s[0]);
    long long ret=0;
    for (int i=1;i<=n;++i){
        long long x=s[i]-limit;
        ret+=getNum(root,x);
        insert(root,s[i]);
    }
    return ret;
}
int main()
{
   long long k;
   scanf("%d%I64d",&n,&k);
    for (int i=0;i<n;++i){
        scanf("%d",&a[i]);
        s[i+1]=s[i]+a[i];
    }
    LL l=-1,r=inf*2;
    while (l+1<r){
        LL mid=(l+r)/2;
        if (calc(mid-inf)>=k) l=mid;
        else r=mid;
    }
    printf("%I64d\n",l-inf);
    return 0;
}
posted @ 2012-06-01 21:13  Because Of You  Views(868)  Comments(0Edit  收藏  举报