zoukankan      html  css  js  c++  java
  • HDU 2852 (树状数组+无序第K小)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2852

    题目大意:操作①:往盒子里放一个数。操作②:从盒子里扔掉一个数。操作③:查询盒子里大于a的第K小数。

    解题思路

    由于模型是盒子,而不是序列,所以可以用树状数组的顺序维护+逆序数思想。

    对应的树状数组Solution:

    放一个数

    $Add(val,1)$

    类似维护逆序数的方法,对应位置上计数+1。

    注意Add的while范围要写成$while(x<maxn)$

    如果范围不是最大,那么会导致某些sum[x]不会被更新。

    删一个数

    判断:$getSum(val)-getSum(val-1)=0$

    可以Hash处理,但是没有必要。如果没有val这个数,那么$getSum(val)=getSum(val-1)$是必然的。

    删除:$Add(val,-1)$

    即加上-1,撤销之前的操作。

    查询

    查询比较麻烦。

    首先要判断$getSum(maxn-1)-getSum(val)>=k$

    然后,将查询大于a的第K小数转化为大于1的第X+K小数。

    其中$X=getSum(val)$。然后,对区间$[1,maxn]$进行二分。

    二分处理手段比较特殊,主要是由于有重复的数,所以直接找出$arg min limits_{mid} getSum(mid)=X+K$是不行的。

    $getSum(mid)=X+K$有时候并不能二分找到。

    解决方法是:

    $left{egin{matrix}
    R=mid quad (getSum(mid)<=X+K)\
    \
    L=mid quad (other)
    end{matrix} ight.$

    这样,如果没有二分到,会最近的最小R作为结果。

    $ans=R$

    代码

    #include "cstdio"
    #include "map"
    #include "cstring"
    #include "algorithm"
    using namespace std;
    #define LL long long
    #define maxn 100005
    LL sum[maxn];
    int val,n,kth,cmd;
    int lowbit(int x) {return x&(-x);}
    LL getSum(int x)
    {
        LL ret=0;
        while(x>0)
        {
            ret+=sum[x];
            x-=lowbit(x);
        }
        return ret;
    }
    void update(int x,int s)
    {
        while(x<maxn)
        {
            sum[x]+=s;
            x+=lowbit(x);
        }
    }
    LL query(int a,int k)
    {
        LL low=getSum(a),res;
        low+=k;
        int l=1,r=maxn-1,m;
        while(l<r-1)
        {
            m=l+(r-l)/2;
            res=getSum(m);
            if(res>=low) r=m;
            else l=m;
        }
        return r;
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        while(scanf("%d",&n)!=EOF)
        {
            memset(sum,0,sizeof(sum));
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&cmd);
                if(cmd==0)
                {
                    scanf("%d",&val);
                    update(val,1);
                }
                else if(cmd==1)
                {
                    scanf("%d",&val);
                    LL key=getSum(val)-getSum(val-1);
                    if(key==0) printf("No Elment!
    ");
                    else update(val,-1);
                }
                else
                {
                    scanf("%d%d",&val,&kth);
                    if(getSum(maxn-1)-getSum(val)<kth) printf("Not Find!
    ");
                    else
                    {
                       LL ans=query(val,kth);
                       printf("%I64d
    ",ans);
                    }
                }
            }
        }
    }
  • 相关阅读:
    ADO.NET批量插入数据方法比较
    Thread was being aborted 分析与解决
    第三方刻录软件介绍
    ASP.NET登陆SQL Server数据库
    word 2010页眉页码从第三页开始设置
    误删除、误格式化后的灾难恢复方案
    Asp.Net4.0新特性概述
    ArcGIS Server的切图原理深入
    ArcGIS的缓存技术
    ArcGIS Server操作Mxd文件详细讲解
  • 原文地址:https://www.cnblogs.com/neopenx/p/4538128.html
Copyright © 2011-2022 走看看