HDU5877Weak Pair
Weak Pair
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Problem Description
You are given a rooted
tree of N
nodes, labeled from 1 to N .
To the i th
node a non-negative value ai
is assigned.An ordered
pair of nodes (u,v)
is said to be weak
if
(1)u
is an ancestor of v
(Note: In this problem a node u
is not considered an ancestor of itself);
(2)au×av≤k .
Can you find the number of weak pairs in the tree?
(1)
(2)
Can you find the number of weak pairs in the tree?
Input
There are multiple cases in the data set.
The first line of input contains an integerT
denoting number of test cases.
For each case, the first line contains two space-separated integers,N
and k ,
respectively.
The second line containsN
space-separated integers, denoting a1
to aN .
Each of the subsequent lines contains two space-separated integers defining an edge connecting nodesu
and v
, where node u
is the parent of node v .
Constrains:
1≤N≤105
0≤ai≤109
0≤k≤1018
The first line of input contains an integer
For each case, the first line contains two space-separated integers,
The second line contains
Each of the subsequent lines contains two space-separated integers defining an edge connecting nodes
Constrains:
Output
For each test case, print a single integer on a single line denoting the number of weak pairs in the tree.
Sample Input
1 2 3 1 2 1 2
Sample Output
1
Source
题意十分明确, 就是求出符合题意的有序点对个数。
首先对ai离散,离散之后的结果用rk[i]表示,然后进行二分预处理得到f[i],其中f[i]的意义为:其他的点和i这个节点满足weakpair要求的权值最大名次(名次权值小的排在前面)。
然后就开始跑一遍DFS,树状数组维护一下答案,就好了。
#include <bits/stdc++.h> using namespace std; #define REP(i,n) for(int i(0); i < (n); ++i) #define rep(i,a,b) for(int i(a); i <= (b); ++i) #define dec(i,a,b) for(int i(a); i >= (b); --i) #define for_edge(i,x) for(int i = H[x]; i; i = X[i]) #define LL long long #define ULL unsigned long long #define MP make_pair #define PB push_back #define FI first #define SE second #define INF 1 << 30 const int N = 300000 + 10; const int M = 10000 + 10; const int Q = 1000 + 10; const int A = 30 + 1; struct Node{ LL num; int id; friend bool operator < (const Node &a, const Node &b){ return a.num < b.num; } } tree[N]; int E[N << 1], X[N << 1], H[N << 1]; LL a[N]; int T, et; int n; LL k; int x, y; LL rk[N], f[N]; LL now; int l, r; bool pa[N]; int root; LL c[N]; LL ans; bool v[N]; inline void addedge(int a, int b){ E[++et] = b, X[et] = H[a], H[a] = et; } inline void add(LL x, LL val){ for (; x <= n; x += (x) & (-x)) c[x] += val; } inline LL query(LL x){ LL ret(0); for (; x; x -= (x) & (-x)) ret += c[x]; return ret; } void dfs(int x){ add(rk[x], 1); for_edge(i, x) if (!v[E[i]]) dfs(E[i]), v[E[i]] = true; add(rk[x], -1); ans += query(f[x]); } int main(){ scanf("%d", &T); while (T--){ et = 0; scanf("%d%lld", &n, &k); rep(i, 1, n) scanf("%lld", a + i); memset(v, false, sizeof v); memset(pa, true, sizeof pa); memset(tree, 0, sizeof tree); memset(H, 0, sizeof H); rep(i, 1, n - 1){ scanf("%d%d", &x, &y); addedge(x, y); pa[y] = false; } rep(i, 1, n){ tree[i].num = a[i]; tree[i].id = i; } sort(tree + 1, tree + n + 1); rk[tree[1].id] = 1; rep(i, 2, n) if (tree[i].num == tree[i - 1].num) rk[tree[i].id] = rk[tree[i - 1].id]; else rk[tree[i].id] = rk[tree[i - 1].id] + 1; rep(i, 1, n){ now = k / a[i]; l = 1; r = n; if (tree[1].num > now) f[i] = 0; else{ while (l + 1 < r){ int mid = (l + r) >> 1; if (tree[mid].num <= now) l = mid; else r = mid - 1; } if (tree[r].num <= now) l = r; f[i] = rk[tree[l].id]; } } root = 0; rep(i, 1, n) if (pa[i]){ root = i; break;} memset(c, 0, sizeof c); ans = 0; v[root] = true; dfs(root); printf("%lld\n", ans); } return 0; }