本题可以看出是算number的个数,重点是转化父子节点的关系,我们可以通过dfs来获得前面需要的节点
注意的是,这个点加完计算后,一定要删除,不然会影响兄弟节点的计算
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<map> #include<set> #include<vector> using namespace std; typedef long long ll; const int N=5e5+10; const ll inf=0x3f3f3f3f; int h[N],ne[N],e[N],in[N]; int idx; int a[N]; int b[N]; ll n; int tr[N]; int size; ll k; ll ans; vector<int> num; void add(int a,int b){ e[idx]=b,ne[idx]=h[a],h[a]=idx++; } int lowbit(int x){ return x&-x; } void modify(int x,int c){ int i; for(i=x;i<=n;i+=lowbit(i)){ tr[i]+=c; } } ll sum(int x){ int i; ll res=0; for(i=x;i;i-=lowbit(i)){ res+=tr[i]; } return res; } void dfs(ll u){ int i; int x=upper_bound(num.begin(),num.end(),k/a[u])-num.begin(); ans+=sum(x); int y=lower_bound(num.begin(),num.end(),a[u])-num.begin()+1; modify(y,1); for(i=h[u];i!=-1;i=ne[i]){ int j=e[i]; dfs(j); } modify(y,-1); } int main(){ int t; cin>>t; while(t--){ idx=0; ans=0; num.clear(); scanf("%d%lld",&n,&k); memset(h,-1,sizeof h); memset(in,0,sizeof in); memset(tr,0,sizeof tr); int i; for(i=1;i<=n;i++){ scanf("%d",&a[i]); num.push_back(a[i]); } sort(num.begin(),num.end()); num.erase(unique(num.begin(),num.end()),num.end()); for(i=1;i<=n-1;i++){ ll b,c; scanf("%lld%lld",&c,&b); add(c,b); in[b]++; } for(i=1;i<=n;i++){ if(!in[i]){ dfs(i); break; } } cout<<ans<<endl; } return 0; }