Weak Pair
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 418 Accepted Submission(s): 151
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) 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?
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
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
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
My Solution
博客里只记录了今天网络赛自己过的题, 队友过的题就不整理上来了 Y ( ^ - ^ ) Y
离散化+树状数组
把祖先节点的值 作为下标 插入的树状数组里, 即 val 的位置插入一个 1, add(val, 1),
然后到当前位置是 get(k / val) 就是 当前满足条件的祖先节点,
回溯的时候把当前的祖先节点pop掉, 即 在 val 位置 插入 一个 -1 , add(val, -1) 这样 就可以维护成 树状数组里记录的 都是当前节点的祖先节点 也是 所有祖先节点。
然后就是 val < 1e9, 直接使用 树状数组必然不行, 所以 我们 进行离散化, 把 n 个 val[i] 和 n 个 k / val[i] (其中 val[i] > k 时 直接 把 val[i] push 进去, 然后最后 这些 祖先节 点 不考虑的),
sort(Ind.begin(),Ind.end());
Ind.erase(unique(Ind.begin(),Ind.end()), Ind.end());
int sz = Ind.size();
Ind.erase(unique(Ind.begin(),Ind.end()), Ind.end());
int sz = Ind.size();
for(int i = 0; i < sz; i++)
mp[Ind[i]]=i+1;
mp[Ind[i]]=i+1;
遍历节点 复杂度 O(n), 使用 树状数组 每次 O(logn)
故 复杂度 O(nlogn)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
#include <vector>
#include <cstring>
using namespace std;
typedef long long LL;
const int maxn = 1*1e5 + 8;
LL val[maxn], k, ans;
map<LL, LL> mp;
vector<int> sons[maxn];
vector<LL> Ind;
LL Tree[2*maxn];
inline LL lowbit(LL x)
{
return (x & -x);
}
inline void add(LL x, LL val)
{
for(LL i = x; i <= 2*maxn; i += lowbit(i))
Tree[i] += val;
}
inline LL get(LL x)
{
LL sum = 0;
for(LL i = x; i; i -= lowbit(i))
sum += Tree[i];
return (sum);
}
void dfs(int u)
{
int sz = sons[u].size();
for(int i = 0; i < sz; i++){
if(val[sons[u][i]] <= k) ans += get(mp[(LL)(k / val[sons[u][i]])]);
add(mp[val[sons[u][i]]], 1);
dfs(sons[u][i]);
add(mp[val[sons[u][i]]], -1);
}
}
bool findroot[maxn];
int main()
{
#ifdef LOCAL
freopen("a.txt", "r", stdin);
//freopen("o.txt", "w", stdout);
#endif // LOCAL
ios::sync_with_stdio(false); cin.tie(0);
int T, n, u, v;
cin >> T;
while(T--){
memset(Tree, 0, sizeof Tree);
cin >> n >> k;
for(int i = 1; i <= n; i++){
cin >> val[i];
Ind.push_back(val[i]);
}
for(int i = 1; i < n; i++){
cin >> u >> v;
sons[u].push_back(v);
}
for(int i = 1; i <= n; i++){
if(k >= val[i]){
Ind.push_back((LL)(k / val[i]));
}
else{
Ind.push_back(val[i]);
}
}
sort(Ind.begin(), Ind.end());
Ind.erase(unique(Ind.begin(), Ind.end()), Ind.end());
int sz = Ind.size();
for(int i = 0; i < sz; i++){
mp[Ind[i]] = i + 1;
//cout << Ind[i] << " " << i + 1 << endl;
}
//buiuld
int root = 1;
memset(findroot, false, sizeof findroot);
for(int i = 1; i <= n; i++){
int sz = sons[i].size();
for(int j = 0; j < sz; j++){
findroot[sons[i][j]] = true;
}
}
for(int i = 1; i <= n; i++){
if(!findroot[i]){
root = i;
break;
}
}
ans = 0;
add(mp[val[root]], 1);
dfs(root);
cout << ans << endl;
for(int i = 1; i <= n; i++) sons[i].clear();
Ind.clear();
}
return 0;
}
Thank you!
------from ProLights