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;

}

你可能感兴趣的:(codeforces)