• 51nod 1685 第 K 大区间 2


    题目大意:定义一个长度为奇数的区间的值为其所包含的的元素的中位数。现给出$n$个数的集合$a$,求将所有长度为奇数的区间的值排序后,第$K$大的值为多少。

    思路:

    考场上的我没有思路,于是弱智的我只会$60pts$主席树。

    正解:

    发现将数列排序后,所求的答案具有单调性。于是可以二分答案。

    但是如何很快的求出一个区间的中位数呢?

    我们可以将数列里大于当前二分查找的值的数置为1,等于的置为0,小于的置为-1。

    这样,一个区间的和如果是0,中位数就是二分查找的数。

    所以用树状数组维护区间和就好了。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define lowbit(x) x&-x
    using namespace std;
    int c[500005][2];
    int a[500005],b[500005],d[500005];
    int sum[500005];
    int del=100005;
    int n,m;
    void add(int x,int num,int opt)
    {
        int i;
        for(i=x;i<=500000;i+=lowbit(i))
            c[i][opt]+=num;
    }
    int query(int x,int opt)
    {
        int sum=0;
        for(int i=x;i;i-=lowbit(i))
            sum+=c[i][opt];
        return sum;
    }
    int check(int k)
    {
        memset(c,0,sizeof(c));
        int i;
        int num1=0,num2=0;
        add(del,1,0);
        for(i=1;i<=n;i++)
        {
            if(a[i]<k)
                d[i]=-1;
            else if(a[i]==k)
                d[i]=0;
            else
                d[i]=1;
            sum[i]=sum[i-1]+d[i];
            add(sum[i]+del,1,i%2);
            num1+=query(sum[i]+del,(i%2)^1)-query(sum[i]+del-1,(i%2)^1);
            num2+=query(sum[i]+del-1,(i%2)^1);
        }
        if(m>num1+num2)
            return 1;
        else if(m<num2)
            return 0;
        return 2;
    }
    int main()
    {
        freopen("Kth.in","r",stdin);
        freopen("Kth.out","w",stdout);
        scanf("%d%d",&n,&m);
        int i,j,l,r;
        for(i=1;i<=n;i++)
            scanf("%d",&a[i]),b[i]=a[i];
        sort(b+1,b+n+1);
        l=1;
        r=n;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            int tmp=check(b[mid]);
            if(tmp==1)
                r=mid-1;
            else if(tmp==0)
                l=mid+1;
            else
            {
                cout<<b[mid];
                break;
            }
        }
    }
  • 相关阅读:
    KMP的next
    关于codeblocks左边文件栏不见的问题
    数据结构第二章内容
    设置notepad++ 的 tab 设为4个空格和设置为中文语言
    字面量
    ..没什么
    今天做的HTML练习
    DAY 145 django的聚合函数和aggregate、annotate方法使用
    DAY 144 Math.round()/Math.ceil()/Math.floor()差异
    DAY 143 DRF-Django rest framework
  • 原文地址:https://www.cnblogs.com/handsome-wjc/p/11291322.html
Copyright © 2020-2023  润新知