HDU 5877 Weak Pair

题目:Weak Pair

链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5877

题意:给一棵树和一个定值k,每个点的值w,对于两点(u、v),如果u 是v 的祖先,且w[u]*w[v]<=k,则说u、v是弱的,问树中有多少对u、v是弱的。

思路:

  第一个要求u 是v 的祖先,那么可以dfs,遍历到v时,所有他上方的都是满足第一条件的u,做多了树就很容易想到在退出某个子树的时候消除这个影响,这样就能保证所有有影响的都是祖先。要求w[u]*w[v]<=k,那么到v的时候,所有小于等于k/w[v]的u都满足,可以想到树状数组。结点的值最大10亿,肯定要离散化,离散化的时候要把k/w[v]加进去一起离散。

AC代码:

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 #include<math.h>
  5 #include<set>
  6 #include<map>
  7 #include<list>
  8 #include<stack>
  9 #include<queue>
 10 #include<vector>
 11 #include<string>
 12 #include<iostream>
 13 #include<algorithm>
 14 using namespace std;
 15 #define lson rt<<1
 16 #define rson rt<<1|1
 17 #define N 100010
 18 #define M 100010
 19 #define Mod 1000000007
 20 #define LL long long
 21 #define INF 0x7fffffff
 22 #define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;i++)
 23 #define For(i,f_start,f_end) for(int i=f_start;i<f_end;i++)
 24 #define REP(i,f_end,f_start) for(int i=f_end;i>=f_start;i--)
 25 #define Rep(i,f_end,f_start) for(int i=f_end;i>f_start;i--)
 26 #define MT(x,i) memset(x,i,sizeof(x))
 27 #define gcd(x,y) __gcd(x,y)
 28 const double PI = acos(-1);
 29 
 30 int c[N<<1];
 31 int Lowbit(int x)
 32 {
 33   return x&(-x);
 34 }
 35 int getsum(int pos)
 36 {
 37   int sum=0;
 38   while(pos>0)
 39   {
 40     sum+=c[pos];
 41     pos-=Lowbit(pos);
 42   }
 43   return sum;
 44 }
 45 void update(int pos,int num,int n)
 46 {
 47    while(pos<=n)
 48    {
 49      c[pos]+=num;
 50      pos+=Lowbit(pos);
 51    }
 52 }
 53 
 54 int n;
 55 LL sum,k;
 56 LL w[N<<1];
 57 vector<int> v[N];
 58 int p[N<<1];
 59 int xin;
 60 void dfs(int rt)
 61 {
 62   int pos;
 63   pos=w[rt+n];
 64   sum += getsum(pos);
 65 
 66   update(w[rt],1,xin);
 67   For(i,0,v[rt].size()){
 68     int son = v[rt][i];
 69     dfs(son);
 70   }
 71   update(w[rt],-1,xin);
 72 }
 73 
 74 bool cmp(int x,int y)
 75 {
 76   return w[x]<w[y];
 77 }
 78 
 79 bool f[N];
 80 int main()
 81 {
 82   int t,x,y;
 83   scanf("%d",&t);
 84   while(t--)
 85   {
 86     scanf("%d%I64d",&n,&k);
 87     FOR(i,1,n){
 88       scanf("%I64d",&w[i]);
 89       if(w[i]==0) w[n+i]=INF;
 90       else w[n+i]=k/w[i];
 91       p[i]=i;
 92       p[n+i]=n+i;
 93     }
 94     sort(p+1,p+n+n+1,cmp);
 95     xin = 0;
 96     int pre = -1;
 97     FOR(i,1,n+n)
 98     {
 99       if(w[p[i]]>pre){ pre=w[p[i]]; w[p[i]]=++xin; }
100       else{ pre=w[p[i]]; w[p[i]]=xin; }
101     }
102     memset(f,0,sizeof(f));
103     For(i,1,n){
104       scanf("%d%d",&x,&y);
105       v[x].push_back(y);
106       f[y]=1;
107     }
108     MT(c,0);
109     sum = 0;
110     FOR(i,1,n){
111       if(f[i]==false)
112       {
113         dfs(i);
114         break;
115       }
116     }
117     printf("%I64d
",sum);
118     FOR(i,1,n){
119       v[i].clear();
120     }
121   }
122   return 0;
123 }
原文地址:https://www.cnblogs.com/hchlqlz-oj-mrj/p/5860653.html