zoukankan      html  css  js  c++  java
  • hdu 4417 划分树

    Super Mario

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 4041    Accepted Submission(s): 1862

    Problem Description
    Mario is world-famous plumber. His “burly” figure and amazing jumping ability reminded in our memory. Now the poor princess is in trouble again and Mario needs to save his lover. We regard the road to the boss’s castle as a line (the length is n), on every integer point i there is a brick on height hi. Now the question is how many bricks in [L, R] Mario can hit if the maximal height he can jump is H.
     
    Input
    The first line follows an integer T, the number of test data.
    For each test data:
    The first line contains two integers n, m (1 <= n <=10^5, 1 <= m <= 10^5), n is the length of the road, m is the number of queries.
    Next line contains n integers, the height of each brick, the range is [0, 1000000000].
    Next m lines, each line contains three integers L, R,H.( 0 <= L <= R < n 0 <= H <= 1000000000.)
     
    Output
    For each case, output "Case X: " (X is the case number starting from 1) followed by m lines, each line contains an integer. The ith integer is the number of bricks Mario can hit for the ith query.
     
    Sample Input
    1 10 10 0 5 2 7 5 4 3 8 7 7 2 8 6 3 5 0 1 3 1 1 9 4 0 1 0 3 5 5 5 5 1 4 6 3 1 5 7 5 7 3
     
    Sample Output
    Case 1: 4 0 0 3 1 2 0 1 5 1

    题意:

    查找指定区间内比x小的数的个数

    思路:

    稍微修改下划分树,但是不知道为什么一开始想的是二分- -,强行GG。写着很麻烦而且还是错的

    划分数能很方便地求出了区间中小于等于第i个数的个数,在这个基础上稍作修改即可


    /*
    */
    
    #include <functional>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <Map>
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    
    using namespace std;
    
    const int maxn = 100010;
    
    int tree[20][maxn];
    int sorted[maxn];
    int toleft[20][maxn];
    
    void build(int l,int r,int dep)  //模拟快排 并记录左树中比i小的个数
    {
        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;
        int 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;
            return 0;
        }
        int mid = (L+R)>>1;
        int cnt = toleft[dep][r]-toleft[dep][l-1];
        if(sorted[mid] > k)          //如果比分界线小
        {
            int lpos = L+toleft[dep][l-1]-toleft[dep][L-1];
            int rpos = lpos+cnt-1;
            if(rpos >= lpos)
                return query(L,mid,lpos,rpos,dep+1,k);
            return 0;
        }
        else
        {
            int rpos = r+toleft[dep][R]-toleft[dep][r];
            int lpos = rpos-(r-l-cnt);
            return cnt+query(mid+1,R,lpos,rpos,dep+1,k);
        }
    }
    
    
    int main()
    {
        int n,m,T;
        int cas = 1;
        scanf("%d",&T);
        while(T--)
        {
    
            scanf("%d%d",&n,&m);
            for(int i = 1; i <= n; i++)
            {
                scanf("%d",&sorted[i]);
                tree[0][i] = sorted[i];
            }
            sort(sorted+1,sorted+n+1);
            build(1,n,0);
    
            int l,r,to,ans;
            printf("Case %d:
    ",cas++);
            while(m--)
            {
                scanf("%d%d%d",&l,&r,&to);
                l++;
                r++;
                ans = query(1,n,l,r,0,to);
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    





  • 相关阅读:
    MvcApplication 中方法的那点事
    Html 中阻止事件冒泡的三种方法比较
    WPF中 ItemsSource 和DataContext不同点
    解决:Visual Studio 启动就报错退出
    webapi是如何绑定参数的(How WebAPI does Parameter Binding)
    %cd% 和%~dp0%的区别及cd跨盘符切换路径问题
    win10中matlabR2015b安装libsvm
    MATLAB2015b链接MinGW编译器
    网易内推编程题:异或运算求混合颜料的最小种类
    小易喜欢的单词
  • 原文地址:https://www.cnblogs.com/Przz/p/5409636.html
Copyright © 2011-2022 走看看