hdu_5877_Weak Pair(离散+DFS+树状数组)

时间:2023-03-08 21:56:29

题目链接:hdu_5877_Weak Pair

题意:

给你一棵树,让你找有多少对满足那两个条件的weak pair

题解:

有人用Treap,我不会,然后我用树状数组+离散来替代Treap,用DFS搜到叶子,然后在树状数组中找小于k/a[u]的个数,注意a[u]可以为0,要处理一下

 #include<bits/stdc++.h>
#define F(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long ll; const int N=1e5+;
int t,n,v[N],g[N],nxt[N],ed,sum[N],in[N],edn;
ll k,a[N],hsh[N],ans; inline int getid(ll x){return upper_bound(hsh+,hsh++edn,x)-hsh-;}
inline void add(int x,int c){while(x<=n)sum[x]+=c,x+=x&-x;}
inline int ask(int x){int an=;while(x)an+=sum[x],x-=x&-x;return an;} inline void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;} void dfs(int u)
{
add(getid(a[u]),);
for(int i=g[u];i;i=nxt[i])dfs(v[i]);
add(getid(a[u]),-);
ll tp;
if(a[u]!=)tp=k/a[u];else tp=hsh[edn]+;
if(tp>hsh[edn])tp=hsh[edn]+;
ans+=ask(getid(tp));
} int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%lld",&n,&k);
F(i,,n)scanf("%lld",a+i),hsh[i]=a[i];
sort(hsh+,hsh++n),memset(sum,,sizeof(sum));
memset(in,,sizeof(in)),edn=;
memset(g,,sizeof(g)),ed=,ans=;
F(i,,n)if(hsh[i]!=hsh[edn])hsh[++edn]=hsh[i];
F(i,,n-)
{
int x,y;
scanf("%d%d",&x,&y);
adg(x,y),in[y]++;
}
F(i,,n)if(!in[i]){dfs(i);break;}
printf("%lld\n",ans);
}
return ;
}