BSG白山极客挑战赛题解 E 【二分+树状数组】

来源:互联网 发布:大数据预测彩票 编辑:程序博客网 时间:2024/04/28 05:16

链接:http://www.51nod.com/contest/problem.html#!problemId=1685

题意:中文题

分析:二分答案t,统计中位数大于等于t的区间有多少个。 设a[i]为前i个数中有a[i]个数>=t,若奇数区间[l,r]的中位数>=t,则(a[r]-a[l-1])*2>=r-l,即(a[r]*2-r)>=(a[l-1]*2-l)。 设b[i]=a[i]*2-i,统计每个b[i]有多少个b[j]=<b[i](j<i 且 j和i奇偶性不同) 

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<string>#include<vector>#include<queue>#include<cmath>#include<stack>#include<set>#include<map>#define INF 0x3f3f3f3f#define Mn 200010#define Mm 2000005#define mod 1000000007#define CLR(a,b) memset((a),(b), sizeof((a)))#define CPY(a,b) memcpy ((a),(b), sizeof((a)))#pragma comment(linker, "/STACK:102400000,102400000")#define ul u<<1#define ur (u<<1)|1#define pi acos(-1.0)using namespace std;typedef long long ll;int bit[Mn][2];int lowbit(int x) {return x&(-x);}int N=200000;void push(int x,int flag) {    if(x==0) return ;    while(x<=N) {        bit[x][flag]+=1;        x+=lowbit(x);    }}int getSum(int x,int flag) {    int re=0;    while(x>0) {        re+=bit[x][flag];        x-=lowbit(x);    }    return re;}int a[Mm];int b[Mn];int n;ll k;bool check(int x) {    CLR(b,0);    CLR(bit,0);    for(int i=1;i<=n;i++) {        if(a[i]>=x) b[i]=b[i-1]+1;        else b[i]=b[i-1];    }    for(int i=1;i<=n;i++) {        b[i]=b[i]*2-i+100000;    }    ll sum=0;    for(int i=1;i<=n;i++) {        push(b[i],i&1);        if(i&1&&b[i]>100000) sum++;//加上自己        sum+=getSum(b[i],!(i&1));        //cout<<b[i]-1<<" "<<getSum(b[i],!(i&1))<<endl;    }    //cout<<sum<<endl;    if(sum>=k) return true;    else return false;}int main() {    scanf("%d%lld",&n,&k);    int maxx=0;    for(int i=1;i<=n;i++) {        scanf("%d",&a[i]);        maxx=max(maxx,a[i]);    }    int l=0,r=maxx;    while(l<r) {        int mid=(l+r+1)>>1;        if(check(mid)) {            l=mid;        } else r=mid-1;    }    printf("%d\n",l);    return 0;}


0 0
原创粉丝点击