Weak Pair
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 4455 Accepted Submission(s): 1297
Problem Description
You are given a
rooted tree of
N nodes, labeled from 1 to
N. To the
ith node a non-negative value
ai is assigned.An
ordered pair of nodes
(u,v) is said to be
weak if
(1) u is an ancestor of v (Note: In this problem a node u is not considered an ancestor of itself);
(2) au×av≤k.
Can you find the number of weak pairs in the tree?
(1) u is an ancestor of v (Note: In this problem a node u is not considered an ancestor of itself);
(2) au×av≤k.
Can you find the number of weak pairs in the tree?
Input
There are multiple cases in the data set.
The first line of input contains an integer T denoting number of test cases.
For each case, the first line contains two space-separated integers, N and k, respectively.
The second line contains N space-separated integers, denoting a1 to aN.
Each of the subsequent lines contains two space-separated integers defining an edge connecting nodes u and v , where node u is the parent of node v.
Constrains:
1≤N≤105
0≤ai≤109
0≤k≤1018
The first line of input contains an integer T denoting number of test cases.
For each case, the first line contains two space-separated integers, N and k, respectively.
The second line contains N space-separated integers, denoting a1 to aN.
Each of the subsequent lines contains two space-separated integers defining an edge connecting nodes u and v , where node u is the parent of node v.
Constrains:
1≤N≤105
0≤ai≤109
0≤k≤1018
Output
For each test case, print a single integer on a single line denoting the number of weak pairs in the tree.
Sample Input
1 2 3 1 2 1 2
Sample Output
1
题意:
给定有n个节点的树,每个节点有一个值ai,问满足下列两个条件的节点对(u,v)有多少
①u是v的父节点(在本题中u不是u的父节点)
②au*av?<=k
思路:
与子树有关->dfs序
点的ai值过大->离散化
快速查询更改父节点->线段树(树状数组)
线段树维护的是当前已经遍历过的父节点的个数
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <cmath>
#include <vector>
#define max_ 101000
#define inf 0x3f3f3f3f
#define ll long long
#define les 1e-8
using namespace std;
struct node
{
int l,r;
int w;
};
struct node tree[max_*80];
int n,l;
ll k,ans;
ll num[max_*2];
ll val[max_];
vector<int>v[max_];
bool vis[max_];
void built(int i,int l,int r)
{
tree[i].l=l;
tree[i].r=r;
tree[i].w=0;
if(l==r)
return;
int mid=(l+r)>>1;
built(i<<1,l,mid);
built(i<<1|1,mid+1,r);
}
ll query(int i,int l,int r)
{
if(tree[i].l==l&&tree[i].r==r)
return (ll)tree[i].w;
int mid=(tree[i].l+tree[i].r)>>1;
if(r<=mid)
return query(i<<1,l,r);
else if(l>mid)
return query(i<<1|1,l,r);
else
return query(i<<1,l,mid)+query(i<<1|1,mid+1,r);
}
void updata(int i,int k,int v)
{
if(tree[i].l==tree[i].r)
{
tree[i].w+=v;
return;
}
int mid=(tree[i].l+tree[i].r)>>1;
if(k<=mid)
updata(i<<1,k,v);
else
updata(i<<1|1,k,v);
tree[i].w=tree[i<<1].w+tree[i<<1|1].w;
}
void dfs(int x)
{
int q=lower_bound(num+1,num+l,k/val[x])-num;//要寻找的ai值在num数组中的位置
int p=lower_bound(num+1,num+l,val[x])-num;//当前遍历到的父节点在num数组中的位置
ans+=query(1,1,q);//查询在1~ai之间已经有多少个满足条件的父节点
updata(1,p,1);//将当前父节点加入
for(int i=0;i<v[x].size();i++)
dfs(v[x][i]);
updata(1,p,-1);//子树已经搜索完毕,将当前父节点弹出
}
int main(int argc, char const *argv[]) {
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%lld",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%lld",&num[i]);
val[i]=num[i];
v[i].clear();
}
for(int i=n+1;i<=2*n;i++)
num[i]=k/(num[i-n]);
sort(num+1,num+1+n*2);
l=unique(num+1,num+1+2*n)-(num+1);//离散化
built(1,1,l);
memset(vis,false,sizeof vis);
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
v[x].push_back(y);
vis[y]=true;
}
int root;
for(int i=1;i<=n;i++)
{
if(vis[i]==false)//没有在子节点中出现过的就是根节点
{
root=i;
break;
}
}
ans=0;
dfs(root);
printf("%lld\n",ans );
}
return 0;
}