zoukankan      html  css  js  c++  java
  • HDU 5678 ztr loves trees

    这题也是一眼标算.....

    先搞一次dfs,把树转换成序列,对每个节点看子树的中位数,也就是看某段区间的中位数,这样就可以主席树求区间第k大值解决。

    注意:询问的次数有1000000次,每次去询问会TLE的。注意到询问的种类只有100000种,所以之前询问过的可以0(1)得到,或者直接处理出每一种询问的答案。

    还有一个问题:小数取模...用fmod函数。

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<map>
    #include<vector>
    #include<algorithm>
    using namespace std;
    
    inline bool scan_d(int &num)
    {
        char in; bool IsN = false;
        in = getchar();
        if (in == EOF) return false;
        while (in != '-' && (in<'0' || in>'9')) in = getchar();
        if (in == '-'){ IsN = true; num = 0; }
        else num = in - '0';
        while (in = getchar(), in >= '0'&&in <= '9'){
            num *= 10, num += in - '0';
        }
        if (IsN) num = -num;
        return true;
    }
    
    #define mod 1000000007
    const int maxn = 100010;
    double Ans[maxn];
    vector<int>Tree[maxn];
    int tmp_n, Q;
    int val[maxn];
    int L[maxn], R[maxn];
    int time;
    
    const int MAXN = 200010;
    const int M = MAXN * 30;
    int n, q, m, tot;
    int a[MAXN], t[MAXN];
    int T[M], lson[M], rson[M], c[M];
    
    void Init_hash()
    {
        for (int i = 1; i <= n; i++)
            t[i] = a[i];
        sort(t + 1, t + 1 + n);
        m = unique(t + 1, t + 1 + n) - t - 1;
    }
    int build(int l, int r)
    {
        int root = tot++;
        c[root] = 0;
        if (l != r)
        {
            int mid = (l + r) >> 1;
            lson[root] = build(l, mid);
            rson[root] = build(mid + 1, r);
        }
        return root;
    }
    int HASH(int x)
    {
        return lower_bound(t + 1, t + 1 + m, x) - t;
    }
    int update(int root, int pos, int val)
    {
        int newroot = tot++, tmp = newroot;
        c[newroot] = c[root] + val;
        int l = 1, r = m;
        while (l < r)
        {
            int mid = (l + r) >> 1;
            if (pos <= mid)
            {
                lson[newroot] = tot++; rson[newroot] = rson[root];
                newroot = lson[newroot]; root = lson[root];
                r = mid;
            }
            else
            {
                rson[newroot] = tot++; lson[newroot] = lson[root];
                newroot = rson[newroot]; root = rson[root];
                l = mid + 1;
            }
            c[newroot] = c[root] + val;
        }
        return tmp;
    }
    int query(int left_root, int right_root, int k)
    {
        int l = 1, r = m;
        while (l < r)
        {
            int mid = (l + r) >> 1;
            if (c[lson[left_root]] - c[lson[right_root]] >= k)
            {
                r = mid;
                left_root = lson[left_root];
                right_root = lson[right_root];
            }
            else
            {
                l = mid + 1;
                k -= c[lson[left_root]] - c[lson[right_root]];
                left_root = rson[left_root];
                right_root = rson[right_root];
            }
        }
        return l;
    }
    
    void dfs(int now)
    {
        L[now] = ++time;
        a[time] = val[now];
        for (int i = 0; i < Tree[now].size(); i++)
            dfs(Tree[now][i]);
        R[now] = ++time;
        a[time] = val[now];
    }
    
    int main()
    {
        int Case; scanf("%d", &Case);
        while (Case--)
        {
            scanf("%d%d", &tmp_n, &Q);
    
            for (int i = 1; i <= tmp_n; i++)
            {
                scan_d(val[i]);
                Tree[i].clear();
            }
    
            for (int i = 1; i <= tmp_n - 1; i++)
            {
                int u, v;
                scan_d(u); scan_d(v);
                Tree[u].push_back(v);
            }
    
            time = 0; 
            dfs(1);
            n = time;
    
            tot = 0;
            Init_hash();
    
            T[n + 1] = build(1, m);
    
            for (int i = n; i; i--)
            {
                int pos = HASH(a[i]);
                T[i] = update(T[i + 1], pos, 1);
            }
    
            for (int i = 1; i <= tmp_n; i++)
            {
                int l = L[i], r = R[i];
                if ((l - r + 1) % 2 == 1)
                {
                    int k = (l + r) / 2 - l + 1;
                    Ans[i] = 1.0*t[query(T[l], T[r + 1], k)];
                }
                else
                {
                    int k1 = (l + r) / 2 - l + 1;
                    int k2 = (l + r) / 2 - l + 2;
                    Ans[i] = 1.0*(t[query(T[l], T[r + 1], k1)] + t[query(T[l], T[r + 1], k2)]) / 2.0;
                }
            }
            double f = 0;
    
            for (int i = 1; i <= Q; i++)
            {
                int id; scan_d(id);
                f = fmod(f * 10 + Ans[id], mod);
            }
            printf("%.1lf
    ", f);
        }
        return 0;
    }
  • 相关阅读:
    使用PHP建立GIF
    无数据库的详细域名查询程序PHP版
    用PHP实现通过Web执行C/C 程序
    判断一数是否在一已知数组中的函数
    如何将本地项目上传到码云
    IIS服务器,IIS日志文件占用C盘空间,C盘空间不足 常见问题
    谈谈个人能力的系统性
    毕业后5年决定命运
    个人取得工资、薪金所得应当如何缴纳个人所得税
    Chart 控件 for vs2008的安装
  • 原文地址:https://www.cnblogs.com/zufezzt/p/5450499.html
Copyright © 2011-2022 走看看