您的位置:首页 > 大数据 > 人工智能

HDU 5877 Weak Pair(树状数组)

2016-11-17 18:40 429 查看
【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=5877

【题目大意】

  给出一棵带权有根树,询问有几对存在祖先关系的点对满足权值相乘小于等于k。

【题解】

  我们沿根节点开始将点权加入权值树状数组,每次处理完子树就回溯,保证每个节点的答案统计是在只包括祖先节点的树状数组中进行。

【代码】

#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
const int N=100005;
long long a
,disc
,k;
int c
,ans,b
,d
,T,n;
vector<int> v
;
int add(int x,int num){while(x<N)c[x]+=num,x+=x&-x;}
int query(int x){int s=0;while(x)s+=c[x],x-=x&-x;return s;}
int remark(long long x){
int l=1,r=n;
while(l<=r){
int mid=(l+r)>>1;
if(disc[mid]<x)l=mid+1;
else if(disc[mid]==x)return mid;
else r=mid-1;
}
}
void dfs(int x){
add(b[x],1);
for(int i=0;i<v[x].size();i++)dfs(v[x][i]);
long long t=k/a[x];
int u=upper_bound(disc+1,disc+n+1,t)-disc-1;
add(b[x],-1);
ans+=query(u);
}
int main(){
scanf("%d",&T);
while(T--){
memset(d,0,sizeof(d));
memset(c,0,sizeof(c));
for(int i=1;i<=n;i++)v[i].clear();
scanf("%d%lld",&n,&k);
for(int i=1;i<=n;i++)scanf("%lld",a+i),disc[i]=a[i];
sort(disc+1,disc+n+1);
for(int i=1;i<=n;i++)b[i]=remark(a[i]);
for(int i=1;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
v[x].push_back(y);
d[y]++;
}ans=0;
for(int i=1;i<=n;i++)if(!d[i])dfs(i);
printf("%d\n",ans);
}return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: