zoukankan      html  css  js  c++  java
  • 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;
            }
        }
    }
  • 相关阅读:
    linux内核中GNU C和标准C的区别
    linux内核中GNU C和标准C的区别
    Getting start with dbus in systemd (02)
    Getting start with dbus in systemd (01)
    Getting start with dbus in systemd (03)
    物理内存相关的三个数据结构
    数据类型对应字节数(32位,64位 int 占字节数)
    Linux kernel 内存
    共模电感的原理以及使用情况
    [原创]DC-DC输出端加电压会烧毁
  • 原文地址:https://www.cnblogs.com/handsome-wjc/p/11291322.html
Copyright © 2011-2022 走看看