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;
    }
    





  • 相关阅读:
    将make的输出重定向到文件
    ubuntu mount u盘以及cp拷贝文件夹
    Emacs Tutorial摘录
    c#实现每隔一段时间执行代码(多线程)
    socket.BeginReceiveFrom异步接收信息时,回调函数无法正常进入
    23个C#实用技巧
    C#中实现Form的透明属性变化即渐隐效果
    C#键位定制:设置一个文本框只能输入数字键
    byte 与 bit 的转换
    C# Socket UDP 案例 2
  • 原文地址:https://www.cnblogs.com/Przz/p/5409636.html
Copyright © 2011-2022 走看看