题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5877
题意:
求有序对个数(i,j)满足:
i是j的祖先节点,且ai * aj <= k
代码:
//#include <bits/stdc++.h>
#include <algorithm>
#include <cstdio>
#define sf scanf
#define pf printf
using namespace std;
const int maxn = 100000 + 5;
typedef __int64 INT;
int ins[maxn],n;
INT A[maxn], a[maxn],sorted[maxn],k,ans;
INT SUM(int p){
INT ret = 0;
for(;p;p -= p & -p) ret += A[p];
return ret;
}
void ADD(int p,INT v){
for(;p <= n;p += p & -p) A[p] += v;
}
int IDX(INT x){
int idx = upper_bound(sorted + 1,sorted + 1 + n,x) - sorted;
if(idx > n) idx = n;
return idx;
}
struct Edge{
int v,pre;
}Es[maxn];
int head[maxn],tot;
void INIT_EDGE(){
memset(head,-1,sizeof head);
tot = 0;
}
void ADD_EDGE(int u,int v){
Es[tot].v = v;
Es[tot].pre = head[u];
head[u] = tot++;
}
void DFS(int cur){
ans += SUM(a[cur] ? IDX(k / a[cur]) : n);
ADD(IDX(a[cur]),1);
for(int i = head[cur];~i;i = Es[i].pre) DFS(Es[i].v);
ADD(IDX(a[cur]),-1);
}
void INIT(){
INIT_EDGE();
memset(A,0,sizeof A);
memset(ins,0,sizeof ins);
ans = 0;
}
int main(){
int T,u,v,s;sf("%d",&T);
while( T-- ){
INIT();
sf("%d%I64d",&n,&k);
for(int i = 1;i <= n;++i) {sf("%I64d",&a[i]);sorted[i] = a[i];}
for(int i = 0;i < n - 1;++i){sf("%d%d",&u,&v);ins[v]++;ADD_EDGE(u,v);}
for(int i = 1;i <= n;++i) if(ins[i] == 0) {s = i;break;}
sort(sorted + 1,sorted + 1 + n);
DFS(s);
pf("%I64d\n",ans);
}
return 0;
}