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