zoukankan      html  css  js  c++  java
  • HDU 4417 (划分树+区间小于k统计)

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

    题目大意:给定一个区间,以及一个k值,求该区间内小于等于k值的数的个数。注意区间是从0开始的。

    解题思路

    首先这题线段树可以解。方法是维护一个区间最大值max,一个区间点个数s,如果k>max,则ans=s+Q(rson),否则ans=Q(lson)。

    然后也可以用求区间第K大的划分树来解决,在对原来求第K大的基础上改改就行,方法如下:

    Build方法同第K大。

    对于Query:

    ①左区间求法:

    if(sorted[mid]>k)进行左区间查询:注意不能等于k,原因是左区间是不包含sorted[mid];同时左区间中newr=newl+cnt-1,

    当cnt=0时,即k值是当前区间最大值,会导致newl>newr,需要特判.

    ②右区间求法:

    上面的条件else就是右区间,ans=cnt+Q(右区间)

    ③区间l=r时:

    如果tree[dep][l]<=k,则return 1

    反之return 0

     

    模板参照上海大学的模板王kuangbin大神:

     

    #include "cstdio"
    #include "algorithm"
    #include "cstring"
    using namespace std;
    #define maxn 100005
    int tree[20][maxn],sorted[maxn],toleft[20][maxn];
    void Build(int l,int r,int dep)
    {
        if(l==r) return;
        int mid=(l+r)>>1;
        int same=mid-l+1;
        for(int i=l;i<=r;i++)
            if(tree[dep][i]<sorted[mid]) same--;
        int lpos=l,rpos=mid+1;
        for(int i=l;i<=r;i++)
        {
            if(tree[dep][i]<sorted[mid])
                tree[dep+1][lpos++]=tree[dep][i];
            else if(tree[dep][i]==sorted[mid]&&same>0)
            {
                tree[dep+1][lpos++]=tree[dep][i];
                same--;
            }
            else tree[dep+1][rpos++]=tree[dep][i];
            toleft[dep][i]=toleft[dep][l-1]+lpos-l;
        }
        Build(l,mid,dep+1);
        Build(mid+1,r,dep+1);
    }
    int query(int L,int R,int l,int r,int dep,int k)
    {
        if(l==r)
        {
            if(tree[dep][l]<=k) return 1;
            else return 0;
        }
        int mid=(L+R)>>1;
        int cnt=toleft[dep][r]-toleft[dep][l-1];
        if(sorted[mid]>k)
        {
            int newl=L+toleft[dep][l-1]-toleft[dep][L-1];
            int newr=newl+cnt-1;
            if(newr>=newl) query(L,mid,newl,newr,dep+1,k);//如果Q的是区间最大值,则cnt=0,newl>newr
            else return 0;
        }
        else
        {
            int newr=r+toleft[dep][R]-toleft[dep][r];
            int newl=newr-(r-l-cnt);
            return cnt+query(mid+1,R,newl,newr,dep+1,k);
        }
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        int T,n,m,u,v,w,no=0;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&n,&m);
            memset(tree,0,sizeof(tree));
            memset(toleft,0,sizeof(toleft));
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&tree[0][i]);
                sorted[i]=tree[0][i];
            }
            sort(sorted+1,sorted+n+1);
            Build(1,n,0);
            printf("Case %d:
    ",++no);
            while(m--)
            {
                scanf("%d%d%d",&u,&v,&w);
                u++;v++;
                printf("%d
    ",query(1,n,u,v,0,w));
            }
        }
    }
    11836396 2014-10-10 00:48:26 Accepted 4417 187MS 16288K 2014 B C++ Physcal

     

     

  • 相关阅读:
    js的this几种用法
    JS 事件绑定的几种方式 小笔记
    rem和em和px vh vw和% 移动端长度单位
    js 判断字符串中是否有某字符串
    angular2中的DOM操作之如何使input获取焦点
    angular2模板绑定样式
    论vw单位的实用性
    谷歌浏览器关闭同源策略方法
    video字幕无法显示,video视频在google中无法控制快进
    video视频铺满
  • 原文地址:https://www.cnblogs.com/neopenx/p/4014837.html
Copyright © 2011-2022 走看看