题目链接:Weak Pair
题意:
给出一颗有根树,如果有一对u,v,如果满足u是v的父节点且vec[u]×vec[v]<=k,则称这对结点是虚弱的,问这棵树中有几对虚弱的结点。
题解:
刚开始看到这题,无脑暴力dfs从叶子结点向上递归,TLE了一发神清气爽@。@!所以用树状数组优化dfs,从根节点向下递归,在结点x找所有满足<=k/vec[x]的点的个数。这里因为数据很大要离散化一下,在输入的时候就把vec[x]和M/vec[x]都放数组里面,sort一下后再放到map里面。这题学了一下用树状数组优化dfs,感觉挺好的~
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int MAX_N = 1e5+9; 4 vector<int> P[MAX_N]; 5 int in[MAX_N]; 6 long long vec[MAX_N*4]; 7 long long vec1[MAX_N*4]; 8 long long res[MAX_N*4]; 9 long long pos[MAX_N*4]; 10 map<long long ,int > mp; 11 long long ans =0 ; 12 long long N,M,T; 13 void add(int x,long long num) 14 { 15 for(;x<4*MAX_N;x+=(x&-x)) 16 res[x] += num; 17 } 18 long long sum(int x) 19 { 20 long long ans = 0; 21 for(;x>0;x-=(x&-x)) 22 ans += res[x]; 23 return ans; 24 } 25 void dfs(int x) 26 { 27 ans += sum(mp[M/vec[x]]); 28 add(mp[vec[x]],1); 29 for(int i=0;i<P[x].size();i++) 30 { 31 dfs(P[x][i]); 32 } 33 add(mp[vec[x]],-1); 34 } 35 int main() 36 { 37 cin>>T; 38 while(T--) 39 { 40 mp.clear(); 41 memset(in,0,sizeof(in)); 42 memset(res,0,sizeof(res)); 43 for(int i=0;i<MAX_N;i++) P[i].clear(); 44 cin>>N>>M; 45 for(int i=1;i<=N;i++) 46 { 47 scanf("%lld",&vec[i]); 48 vec1[i+N] = M/vec[i]; 49 vec1[i] = vec[i]; 50 } 51 sort(vec1+1,vec1+2*N+1); 52 for(int i=1;i<=2*N;i++) 53 { 54 mp.insert(make_pair(vec1[i],i)); 55 } 56 for(int i=0;i<N-1;i++) 57 { 58 int a,b; 59 scanf("%d%d",&a,&b); 60 P[a].push_back(b); 61 in[b] ++; 62 } 63 int point = 0; 64 for(int i=1;i<=N;i++) 65 { 66 if(!in[i]) 67 { 68 point = i; 69 break; 70 } 71 } 72 ans = 0; 73 dfs(point); 74 cout<<ans<<endl; 75 } 76 return 0; 77 }