HDU5877:Weak Pair(树状数组+离散化+DFS序)
Weak Pair
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 5448 Accepted Submission(s): 1564
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?
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
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
Source
2016 ACM/ICPC Asia Regional Dalian Online
题解:离散化,DFS序,利用树状数组维护前缀和。
对于x,要求y使得x*y<=k的个数,即求y<=k/x的个数,所以只需求用树状数组求小于等于k/x的个数。前提是要离散化
DFS序经过x时求一遍,回到x时再求一遍,两个前缀和一减,便求得y的个数
#include <bits/stdc++.h>
using namespace std;
int const N = 100000 + 10;
typedef long long ll;
ll const inf = 0x3f3f3f3f3f3f3f3f;
ll k,ans,a[N];
int n,t,tot,in[N],c[N],root;
int first[N],ne[2*N],to[2*N];
vector<ll>v;
int lowbit(int i){
return i&-i;
}
void add(int x,int d){
while(x <= v.size()){
c[x] += d;
x += lowbit(x);
}
}
ll query(int x){
ll ret = 0;
while(x){
ret += (ll)c[x];
x -= lowbit(x);
}
return ret;
}
void insert(int x,int y){
ne[++tot] = first[x];
to[tot] = y;
first[x] = tot;
}
void dfs(int x,int fa){
add(lower_bound(v.begin(),v.end(),a[x])-v.begin()+1,1);
int tmp = lower_bound(v.begin(),v.end(),a[x]?k/a[x]:inf)-v.begin()+1;
ll pre = query(tmp);
for(int i=first[x];i;i=ne[i]){
int v = to[i];
if(v == fa) continue;
dfs(v,x);
}
ans += query(tmp) - pre;
}
void Init(){
v.clear();
memset(c,0,sizeof(c));
memset(in,0,sizeof(in));
memset(first,0,sizeof(first));
ans = tot = 0;
scanf("%d%lld",&n,&k);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
v.push_back(a[i]);
if(!a[i]) v.push_back(inf); //a[i]可以为0!!!
else v.push_back(k/a[i]);
}
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
for(int i=1;i<=n-1;i++){ //x是y的父亲,有序
int x,y;
scanf("%d%d",&x,&y);
insert(x,y);
in[y]++;
}
for(int i=1;i<=n;i++) //找到根节点
if(!in[i]){
root = i;
break;
}
}
int main(){
scanf("%d",&t);
while(t--){
Init();
tot = 0;
dfs(root,-1);
printf("%lld\n",ans);
}
}

浙公网安备 33010602011771号