计算一棵树上有多少个u,v对,满足u是v的祖先并且a[u]* a[v]<=k
dfs往下搜的时候,用线段树求[1,k/a[i]]中共有多少元素,然后更新
不怎么会离散化,恩。。。记一下unique函数和lower_boud
m =unique(b+1 ,b+m+1) - (b+1);删除重复元素,并返回最后一个元素的地址
int l =lower_bound(b +1,b+m+1,k/a[u]) - b;
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
#define lson l,m,pos<<1
#define rson m+1,r,pos<<1|1
#define ll long long
#define FOR(i, j, k) for(int i = j;i<=k ;i++)
int mod;
int tree[200010*4];
ll a[100010];
ll b[200010];
int tot;
int head[100010];
int du[100010];
struct Edge{
int v;
int next;
}edge[100010];
void init()
{
tot = 0;
memset(head ,-1 , sizeof(head));
}
void addedge(int u,int v)
{
edge[tot].v = v;
edge[tot].next = head[u];
head[u] = tot++;
}
void Pushup(int pos){
tree[pos] = tree[pos<<1]+ tree[(pos<<1)+1] ;
}
void build(int l, int r, int pos)
{
if(l == r)
{
tree[pos] = 0;
return;
}
int m = (l+r)>>1;
build(lson);
build(rson);
Pushup(pos);
}
void update(int p, int val, int l, int r, int pos)
{
if(l == r)
{
tree[pos] +=val;
return;
}
int m = (l+r) >>1;
if(p <= m) update( p, val,lson);
else update( p, val, rson);
Pushup(pos);
}
ll query(int L, int R, int l ,int r,int pos)
{
if(L <= l && r<=R)
return tree[pos];
ll ans =0;
int m = (l+r) >>1;
if(L <= m) ans += query(L,R, lson);
if(R > m) ans += query(L, R, rson);
return ans;
}
ll ans;
int m;
ll k;
void dfs(int u)
{
int l =lower_bound(b +1, b+m+1, k/a[u]) - b;
ans += query(1, l , 1, m ,1);
int p = lower_bound(b+1, b+1+m, a[u]) -b;
update(p, 1, 1, m, 1);
for(int i = head[u] ;i!= -1; i= edge[i].next)
{
dfs(edge[i].v);
}
update(p, -1, 1, m, 1);
}
int main() {
int T;
scanf("%d" ,&T);
while( T --)
{
int n;
scanf("%d%lld",&n,&k);
FOR(i, 1, n)
{
scanf("%lld" ,&a[i]);
b[i] = a[i];
}
m = n;
FOR(i, 1, n)
{
m++;
b[m] = k/a[i];
}
sort(b +1, b+m+1);
m = unique(b+1 ,b+m+1) - (b+1);
build(1 , m ,1);
init();
memset(du, 0, sizeof(du));
FOR(i, 1, n-1)
{
int u,v;
scanf("%d%d" ,&u,&v);
addedge(u, v);
du[v] ++;
}
ans = 0;
FOR(i, 1, n)
{
if(du[i] == 0)
dfs(i);
}
printf("%lld\n",ans);
}
return 0;
}