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\n", f);
    }
    return 0;
}
时间: 2024-11-05 17:31:24

HDU 5678 ztr loves trees的相关文章

hdu 5677 ztr loves substring 二维费用背包+回文

题目链接: hdu 5677 ztr loves substring 官方题解: //这部分是错的(首先,对于每一个串i跑一次manancher,令g[i][j]=p[j]-1g[i][j]=p[j]−1 这样,g就存储了所有的回文子串的长度 为了方便,把g降到一维表示) 首先,因为字符串长度较小,所以直接二重for循环找就好了,用一个数组 g记录各个回文串的长度 不妨把每一个子串抽象成一个物品 费用为二维的,即{长度,1} 价值是Bool型的 这样就成了一个二维判断可行性费用背包问题 设f(i

hdu 5676 ztr loves lucky numbers(BC——暴力打表+二分查找)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5676 ztr loves lucky numbers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 594    Accepted Submission(s): 257 Problem Description ztr loves luck

HDU 5675 ztr loves math

ztr loves math Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 896    Accepted Submission(s): 347 Problem Description ztr loves research Math.One day,He thought about the "Lower Edition" of

hdu 5676 ztr loves lucky numbers(dfs+离线)

Problem Description ztr loves lucky numbers. Everybody knows that positive integers are lucky if their decimal representation doesn't contain digits other than 4 and 7. For example, numbers 47, 744, 4 are lucky and 5, 17, 467 are not. Lucky number is

hdu 5675 ztr loves math(数学技巧)

Problem Description ztr loves research Math.One day,He thought about the "Lower Edition" of triangle equation set.Such as n=x2−y2. He wanted to know that ,for a given number n,is there a positive integer solutions? Input There are T test cases.

hdu 5676 ztr loves lucky numbers

题目链接:hdu 5676 一开始看题还以为和数位dp相关的,后来才发现是搜索题,我手算了下,所有的super lucky number(也就是只含数字4, 7且4, 7的数量相等的数)加起来也不过几万个,可以采用打表的方法来把所有的super lucky number存储起来.因为4,7数量须相等,所以可以用一个二进制数的0,1来代替,先限定4,7数量分别为 i,之后就是求出包含 i 个0和 i 个1的 2*i 位所有这样的二进制数,然后简单转换一下(1->7, 0->4,这样子能从小到大

hdu 5677 ztr loves substring(manacher,背包问题)

1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 5 /** 6 7 8 manacher 处理出回文串长度 9 p[i]:半径 10 11 if(s[i] == '#' && p[i] == 1) continue; 12 else{ 13 int tmp = p[i] / 2; 14 if(s[i] == '#') for(int i = 2 ; i <= tmp ;

HDU 5677 ztr loves substring

Manacher+二维费用多重背包 二进制优化 这题是一眼标算....先计算出每个长度的回文串有几种,然后用二维费用的多重背包判断是否有解. 多重背包做的时候需要二进制优化. #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int maxn = 300; int N, p[maxn]; char str[maxn

[HDU5677]ztr loves substring

ztr loves substring Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem Description ztr love reserach substring.Today ,he has n string.Now ztr want to konw,can he take out exactly k palindrome from all substrin