HDU 5877 Weak Pair(弱点对)

HDU 5877 Weak Pair(弱点对)

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)


Description


题目描述


You are given a rooted tree of N nodes, labeled from 1 to N. To the ith 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?


给你有N个节点的有根树,编号从1到N。第i个节点会被分配一个非负数ai。一个满足如下条件的有序点对(u, v)则被认为是弱点对

(1)uv的先祖节点(注意:这个问题中u不能为自身的先祖节点)。

(2) au X av k

你能找出这棵树里有多少弱点对吗?


Input


输入


There are multiple cases in the data set.

The first line of input contains an integer T denoting number of test cases.

For each case, the first line contains two space-separated integers, N and k, respectively.

The second line contains N space-separated integers, denoting a1 to aN.

Each of the subsequent lines contains two space-separated integers defining an edge connecting nodes u and v , where node u is the parent of node v.

Constrains:

1≤N≤105

0≤ai≤109

0≤k≤1018


多组测试用例。

输入的第一行有一个整数T表示测试用例的数量。

对于每个测试用例,第一行有两个用空格分隔的整数,Nk

第二行有N个用空格分隔的整数,表示a1aN

随后每(N-1)行有两个用空格分隔的数uv表示连接两节点的一条边,其中uv的父节点。

范围如下:

1≤N≤105

0≤ai≤109

0≤k≤1018


Output


输出


For each test case, print a single integer on a single line denoting the number of weak pairs in the tree.


对于每个测试用例,输出一个表示树中弱点对数量的整数在单独一行。


Sample Input - 输入样例


Sample Output - 输出样例


1
2 3
1 2
1 2


1

【题解】

DFS + 离散化线段树

用DFS从上往下(从根往叶子)添加与释放节点进线段树,利用线段树查找符合的区间中元素数量。

因为单个数的值比较大,但是总数比较少,线段树还算可以接受。根据总数进行离散化,其实就是排个序+map。出于想用upper_bound的强迫症没有把k/ai的结果一并加入离散化(注意0),不然代码量应该更少。

【代码 C++】

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <map>
 5 #define LL __int64
 6 #define mx 100005
 7 std::map<LL, int> mp;
 8 LL data[mx], dMP[mx], opt, k;
 9 int n;
10
11 struct Edge{
12     int to, next;
13 }edge[mx];
14 int iE, head[mx], d[mx], tr[mx << 2], fid;
15 void addEdge(int u, int v){
16     edge[iE].to = v; edge[iE].next = head[u]; head[u] = iE++;
17 }
18
19 void cnt(int l, int r, int now){
20     if (r <= fid){ opt += tr[now]; return; }
21     int mid = l + r >> 1;
22     if (fid <= mid) return cnt(l, mid, now << 1);
23     opt += tr[now << 1]; return cnt(mid + 1, r, now << 1 | 1);
24 }
25 void sub(int l, int r, int now){
26     --tr[now];
27     if (l == r) return;
28     int mid = l + r >> 1;
29     if (fid <= mid) return sub(l, mid, now << 1);
30     return sub(mid + 1, r, now << 1 | 1);
31 }
32 void add(int l, int r, int now){
33     ++tr[now];
34     if (l == r) return;
35     int mid = l + r >> 1;
36     if (fid <= mid) return add(l, mid, now << 1);
37     return add(mid + 1, r, now << 1 | 1);
38 }
39
40 void DFS(int now){
41     int u;
42     LL temp;
43     if (data[now] == 0 || (temp = k / data[now]) >= dMP[n]) fid = n;
44     else fid = std::upper_bound(dMP + 1, dMP + 1 + n, temp) - dMP - 1;
45     if (fid) cnt(1, n, 1);
46     fid = mp[data[now]]; add(1, n, 1);
47     for (u = head[now]; ~u; u = edge[u].next) DFS(edge[u].to);
48     fid = mp[data[now]]; sub(1, n, 1);
49 }
50
51 int main(){
52     int t, i, u, v;
53     scanf("%d", &t);
54     while (t--){
55         mp.clear(); memset(tr, 0, sizeof(tr));
56         scanf("%d%I64d", &n, &k);
57         for (i = 1; i <= n; ++i) scanf("%I64d", &data[i]);
58         memcpy(dMP, data, sizeof(data));
59         std::sort(dMP + 1, dMP + n + 1);
60         for (i = 1; i <= n; ++i) mp[dMP[i]] = i;
61
62         memset(head, -1, sizeof(head)); memset(d, 0, sizeof(d));
63         iE = 0;
64         for (i = 1; i < n; ++i){
65             scanf("%d%d", &u, &v);
66             addEdge(u, v); ++d[v];
67         }
68
69         for (i = 1; d[i]; ++i);
70         opt = 0; DFS(i);
71         printf("%I64d\n", opt);
72     }
73     return 0;
74 }
时间: 2024-08-25 09:11:25

HDU 5877 Weak Pair(弱点对)的相关文章

树形DP+树状数组 HDU 5877 Weak Pair

1 //树形DP+树状数组 HDU 5877 Weak Pair 2 // 思路:用树状数组每次加k/a[i],每个节点ans+=Sum(a[i]) 表示每次加大于等于a[i]的值 3 // 这道题要离散化 4 5 #include <bits/stdc++.h> 6 using namespace std; 7 #define LL long long 8 typedef pair<int,int> pii; 9 const double inf = 12345678901234

HDU 5877 Weak Pair

题目:Weak Pair 链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5877 题意:给一棵树和一个定值k,每个点的值w,对于两点(u.v),如果u 是v 的祖先,且w[u]*w[v]<=k,则说u.v是弱的,问树中有多少对u.v是弱的. 思路: 第一个要求u 是v 的祖先,那么可以dfs,遍历到v时,所有他上方的都是满足第一条件的u,做多了树就很容易想到在退出某个子树的时候消除这个影响,这样就能保证所有有影响的都是祖先.要求w[u]*w

hdu 5877 Weak Pair dfs序+树状数组+离散化

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 ith node a non-negative value ai is assigned.An ordered pair of no

2016 ACM/ICPC Asia Regional Dalian Online HDU 5877 Weak Pair treap + dfs序

Weak Pair Problem Description You are given a rooted tree of N nodes, labeled from 1 to N. To the ith 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 no

hdu 5877 Weak Pair(Treap平衡树 + dfs)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5877 题意:在一棵树上,每个节点有一个数值,问有多少对节点满足条件. 对于一对节点(u, v), 若满足 u 为 v的祖先节点且u,v节点上的数值乘积小于 k. 思路: dfs遍历树,对于每个节点 i 查询其祖先节点中,有多少个节点的值小于等于 k / ai(ai为当前节点的数值). dfs过程中,动态把祖先节点插入treap树中,退栈时删除. 1 #include <iostream> 2 #i

HDU 5877 Weak Pair(树状数组+dfs+离散化)

http://acm.hdu.edu.cn/showproblem.php?pid=5877 题意: 给出一棵树,每个顶点都有权值,现在要你找出满足要求的点对(u,v)数,u是v的祖先并且a[u]*a[v]<=k. 思路: 转化一下,a[v]<=k/a[u],k/a[u]的最大值也就是k/a[v],也就是寻找<=k/a[v]的个数,到这儿,是不是很像树状数组? 我们只需要从根开始dfs,插入到树状数组中,并且查询即可.注意这道题目需要离散化一下. 1 #include <iostr

HDU 5877 Weak Pair DFS + 树状数组 + 其实不用离散化

http://acm.hdu.edu.cn/listproblem.php?vol=49 给定一颗树,然后对于每一个节点,找到它的任何一个祖先u,如果num[u] * num[v] <= k.则贡献加1 思路:主要的麻烦就是动态修改前缀和了.因为对于每个数字val.则找它祖先的话, <= k / val的数字,都是合法的.所以问题转化成求你现在dfs中保存的数字,有多少个是  <= k / val的,树状数组即可. 问题就是,数字太大了,这不适合树状数组,那么我们把每个数字离散成他们的下

HDU 5877 dfs+ 线段树(或+树状树组)

1.HDU 5877  Weak Pair 2.总结:有多种做法,这里写了dfs+线段树(或+树状树组),还可用主席树或平衡树,但还不会这两个 3.思路:利用dfs遍历子节点,同时对于每个子节点au,查询它有多少个祖先av满足av<=k/au. (1)dfs+线段树 #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm>

hdu 5877 线段树(2016 ACM/ICPC Asia Regional Dalian Online)

Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 439    Accepted Submission(s): 155 Problem Description You are given a rooted tree of N nodes, labeled from 1 to N. To the ith node a