HDU 5678 ztr loves trees

时间:2023-03-09 02:24:32
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<'' || in>'')) in = getchar();
if (in == '-'){ IsN = true; num = ; }
else num = in - '';
while (in = getchar(), in >= ''&&in <= ''){
num *= , num += in - '';
}
if (IsN) num = -num;
return true;
} #define mod 1000000007
const int maxn = ;
double Ans[maxn];
vector<int>Tree[maxn];
int tmp_n, Q;
int val[maxn];
int L[maxn], R[maxn];
int time; const int MAXN = ;
const int M = MAXN * ;
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 = ; i <= n; i++)
t[i] = a[i];
sort(t + , t + + n);
m = unique(t + , t + + n) - t - ;
}
int build(int l, int r)
{
int root = tot++;
c[root] = ;
if (l != r)
{
int mid = (l + r) >> ;
lson[root] = build(l, mid);
rson[root] = build(mid + , r);
}
return root;
}
int HASH(int x)
{
return lower_bound(t + , t + + m, x) - t;
}
int update(int root, int pos, int val)
{
int newroot = tot++, tmp = newroot;
c[newroot] = c[root] + val;
int l = , r = m;
while (l < r)
{
int mid = (l + r) >> ;
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 + ;
}
c[newroot] = c[root] + val;
}
return tmp;
}
int query(int left_root, int right_root, int k)
{
int l = , r = m;
while (l < r)
{
int mid = (l + r) >> ;
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 + ;
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 = ; 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 = ; i <= tmp_n; i++)
{
scan_d(val[i]);
Tree[i].clear();
} for (int i = ; i <= tmp_n - ; i++)
{
int u, v;
scan_d(u); scan_d(v);
Tree[u].push_back(v);
} time = ;
dfs();
n = time; tot = ;
Init_hash(); T[n + ] = build(, m); for (int i = n; i; i--)
{
int pos = HASH(a[i]);
T[i] = update(T[i + ], pos, );
} for (int i = ; i <= tmp_n; i++)
{
int l = L[i], r = R[i];
if ((l - r + ) % == )
{
int k = (l + r) / - l + ;
Ans[i] = 1.0*t[query(T[l], T[r + ], k)];
}
else
{
int k1 = (l + r) / - l + ;
int k2 = (l + r) / - l + ;
Ans[i] = 1.0*(t[query(T[l], T[r + ], k1)] + t[query(T[l], T[r + ], k2)]) / 2.0;
}
}
double f = ; for (int i = ; i <= Q; i++)
{
int id; scan_d(id);
f = fmod(f * + Ans[id], mod);
}
printf("%.1lf\n", f);
}
return ;
}