• 51 NOD 1685 第K大区间2 二分+BIT


    题目描述:

      定义一个长度为奇数的区间的值为其所包含的的元素的中位数。

      现给出n个数,求将所有长度为奇数的区间的值排序后,第K大的值为多少。

      样例解释:


      [l,r]表示区间的值
      [1]:3
      [2]:1
      [3]:2
      [4]:4
      [1,3]:2
      [2,4]:2


      第三大是2

    输入:

      第一行两个数n和k(1<=n<=100000,k<=奇数区间的数量) 第二行n个数,0<=每个数<2^31

    输出:

      一个数表示答案。

    题解:

      二分答案t,统计中位数大于等于t的区间有多少个。

       设a[i]为前i个数中有a[i]个数>=t,若奇数区间[l,r]的中位数>=t,

      则(a[r]-a[l-1])*2>=r-l+1,即(a[r]*2-r)>=(a[l-1]*2-l+1)。

      b[i]=a[i]*2-i,

      这样题目就变成了统计 b[i]>=b[j] i与j奇偶性不同,BIT

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 2e6+20, M = 1e5+10, mod = 1e9+7, inf = 2e9;
    typedef long long ll;
    
    int C[N][2],n;
    int a[N],b[N];
    ll k;
    void update(int x,int p) {
        if(x==0) return ;
        for(int i=x;i<N;i+=i&(-i)) C[i][p]+=1;
    }
    int getsum(int x,int p) {
        int s = 0;
        for(int i=x;i;i-=i&(-i)) s+=C[i][p];
        return s;
    }
    ll ask(int t)
    {
        memset(C,0,sizeof(C));
        b[0]=0;
        for(int i=1;i<=n;i++) b[i]=a[i]>=t?1:0,b[i]+=b[i-1];
        for(int i=1;i<=n;i++) b[i] = b[i]*2-i+M;
        ll s=0;
        update(M,0);
        for(int i=1;i<=n;i++) {
            s+=getsum(b[i],(i&1)^1);
            update(b[i],(i&1));
        }
        return s;
    }
    int main(){
        scanf("%d%lld",&n,&k);
        int mx = 0;
        for(int i=1;i<=n;i++) scanf("%d",&a[i]),mx = max(mx, a[i]);
        int l=0,r=mx,ans=0;
       // cout<<ask(2)<<endl;//return 0;
        while(l<=r) {
            int mid = (l+r)>>1;
            if(ask(mid)>=k) l=mid+1,ans=mid;
            else r=mid-1;
        }
        printf("%d
    ",ans);
    }
  • 相关阅读:
    ios入门笔记(创建隐式首选项,实现系统设置,实现文件系统存储)
    ios开发(表视图)
    Android上使用OpenglES2.0遇到的一点问题
    Android平台对H264视频硬解码
    Java GC机制和对象Finalize方法的一点总结
    JVM GC之一找出不可达对象并回收
    docker 使用Data Volume 共享文件
    sscanf函数用法详解
    va_start和va_end使用详解
    NDK 的helloworld步奏
  • 原文地址:https://www.cnblogs.com/zxhl/p/5664723.html
Copyright © 2020-2023  润新知