【题意】
给你一棵有根树,一个定值k,以及树上每个结点的值a[i]
对于有序对(u,v),如果(1)u是v的祖先,且(2)a[u]*a[v]<=k,则称该有序对(u,v)是弱的
问树中有多少对有序对(u,v)是弱的
【类型】
离散化+dfs+树状数组
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <map>
using namespace std;
const int maxn = 100010;
#define LL long long
LL n,k,a[maxn],ans;
map<LL,LL> mp;
vector<LL> sons[maxn];
vector<LL> b;
LL tree[2*maxn];
bool findroots[maxn];
int root;
int lowbit(LL x)
{
return x&-x;
}
void add(LL x,LL val)
{
for(LL i = x;i<2*maxn;i += lowbit(i))
tree[i] += val;
}
LL getx(LL x)
{
LL sum = 0;
for(LL i=x;i;i -= lowbit(i))
sum += tree[i];
return sum;
}
void init()
{
ans =0;
mp.clear();
memset(a,0,sizeof(a));
b.clear();
memset(tree,0,sizeof(tree));
memset(findroots,false,sizeof(findroots));
}
void dfs(LL u)
{
//printf("dfs...\n");
int sz = sons[u].size();
for(int i=0;i<sz;i++)
{
if(a[sons[u][i]]<=k) ans += getx(mp[(LL)k/a[sons[u][i]]]);
add(mp[a[sons[u][i]]],1);
dfs(sons[u][i]);
add(mp[a[sons[u][i]]],-1);
}
}
void solve()
{
scanf("%lld %lld",&n,&k);
init();
LL x,y;
for(int i=1; i<=n; i++)
{
scanf("%lld",&a[i]);
if(a[i]>k)
{
b.push_back(a[i]);
}
else
{
b.push_back(k/a[i]);
b.push_back(a[i]);
}
}
sort(b.begin(),b.end());
b.erase(unique(b.begin(),b.end()),b.end());
for(LL i=0;i<(LL)b.size();i++)
{
mp[b[i]] = i+1;
// printf(" %lld %lld\n",b[i],i+1);
}
for(int i=0; i<n-1; i++)
{
scanf("%lld %lld",&x,&y);
sons[x].push_back(y);
}
// cout << " what ..." << endl;
for(int i=1;i<=n;i++)
{
int sz = sons[i].size();
for(int j=0;j<sz;j++)
{
findroots[sons[i][j]] = true;
}
}
//int root = 1;
for(int i=1;i<=n;i++)
{
if(!findroots[i])
{
root = i;
break;
}
}
//printf("root = %lld\n",root);
add(mp[a[root]],1);
dfs(root);
printf("%lld\n",ans);
for(int i=0;i<=n;i++)
{
sons[i].clear();
}
}
int main()
{
int cas;
scanf("%d",&cas);
while(cas--)
{
solve();
}
}