• hdu 4251 The Famous ICPC Team Again


    hdu 4251 The Famous ICPC Team Again 划分树
    //hdu 4251 The Famous ICPC Team Again
    //划分树
    
    //求中位数(就是求中间大的)
    //建树和查找,模板题,看代码
    //不懂可以看看这人写的
    //http://www.cnblogs.com/183zyz/archive/2012/08/01/2618295.html
    
    #define infile freopen("in.txt", "r", stdin);
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #define N 100005
    
    using namespace std;
    
    struct NODE
    {
        int l, r;
    }tree[4*N];
    
    
    int sorted[N], level[20][N];//level记录每一层每个段的序列
    int l_cnt[20][N];   //记录left到right中进入
    
    void build(int left, int right, int loc, int dep)
    {
        tree[loc].l = left;
        tree[loc].r = right;
        if(left == right)
            return;
    
        int mid = left + (right-left)/2;
    
        int mid_val = sorted[mid];
    
        int cnt = 0;    //记录小于left到right这段的中值的个数
        for(int i = left; i <= right; ++i)
            if(level[dep][i] < mid_val)
                cnt++;
    
        //这里l_tot是从left开始···
        int l_tot = left, r_tot = mid + 1;
        int equal_cnt = 0;  //equal_cnt记录跟mid_val相等且进入左子树的个数
        for(int i = left; i <= right; ++i)
        {
            if(level[dep][i] < mid_val) //小于mid_val的进入左子树
                level[dep+1][l_tot++] = level[dep][i];
            else if(level[dep][i] == mid_val && mid-left+1 - cnt > equal_cnt)
            {   //等于mid_val的且没超过左子树限定个数的时候进入左子树
                equal_cnt++;
                level[dep+1][l_tot++] = level[dep][i];
            }
            else
                level[dep+1][r_tot++] = level[dep][i];
            l_cnt[dep][i] = l_tot - left;   //记录进入左子树的个数
        }
        build(left, mid, 2*loc, dep+1);
        build(mid+1, right, 2*loc+1, dep+1);
    }
    
    int ans;
    void find(int loc, int from, int to, int dep, int aim)
    {
        int left = tree[loc].l, right = tree[loc].r;
        if(left == right)
        {
            ans = level[dep][left];
            return;
        }
        int mid = left + (right-left)/2;
    
        //l_from记录当前层中,from以前的数进入左子树的个数(不包括from这个数)
        //l_to记录当前层中,to以前的数进入又子树的个数,包括to
        int l_from, l_to = l_cnt[dep][left+to-1];
        if(from > 1)
            l_from = l_cnt[dep][from+left-2];
        else
            l_from = 0;
    
        //接下去那层就应该保持和这层一样的起点,即from左边的个数不变
        //若下一层到左子树,则要从from以左的进入左子树的个数(from_cnt)开始
        //由于from这个数也到左子树所以下一层应从from_cnt+1开始
        //若下一层到右子树要去掉进入左子树的个数
        if(l_to - l_from >= aim)    //from到to之间进入左子树的个数
            find(2*loc, l_from+1, l_to, dep+1, aim);
        else
            find(2*loc+1, from-1-l_from+1, to-l_to, dep+1, aim-(l_to-l_from));
    }
    
    int main()
    {
        //infile
        int n, n_case = 1;;
        while(scanf("%d", &n) != EOF)
        {
            printf("Case %d:\n", n_case++);
            for(int i = 1; i <= n; ++i)
            {
                scanf("%d", &level[1][i]);
                sorted[i] = level[1][i];
            }
            sort(sorted+1, sorted+n+1);
            build(1, n, 1, 1);
            int n_query;
            scanf("%d", &n_query);
            while(n_query--)
            {
                int from, to;
                scanf("%d%d", &from, &to);
                find(1, from, to, 1, (to-from)/2+1);
                printf("%d\n", ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    pickle 序列化对象
    字符串模板
    静态类和静态方法,抽象类和抽象方法,new关键字,值类型和引用类型,接口
    C#中方法,方法声明,方法调用和方法重载!
    TryParse用法
    成倍提高服务器的负载能力:浅谈Jexus的ASP.NET前置缓存技术
    全面解析C#中参数传递
    【NX二次开发】Block UI 属性类型
    【NX二次开发】镜像对象
    【NX二次开发】根据视图名称旋转视图,在布局中替换视图uc6464
  • 原文地址:https://www.cnblogs.com/gabo/p/2634353.html
Copyright © 2020-2023  润新知