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\n",sum);
118     FOR(i,1,n){
119       v[i].clear();
120     }
121   }
122   return 0;
123 }
时间: 2024-08-06 14:24:15

HDU 5877 Weak Pair的相关文章

HDU 5877 Weak Pair(弱点对)

HDU 5877 Weak Pair(弱点对) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) 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 ordere

树形DP+树状数组 HDU 5877 Weak Pair

1 //树形DP+树状数组 HDU 5877 Weak Pair 2 // 思路:用树状数组每次加k/a[i],每个节点ans+=Sum(a[i]) 表示每次加大于等于a[i]的值 3 // 这道题要离散化 4 5 #include <bits/stdc++.h> 6 using namespace std; 7 #define LL long long 8 typedef pair<int,int> pii; 9 const double inf = 12345678901234

hdu 5877 Weak Pair dfs序+树状数组+离散化

Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) 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 no

2016 ACM/ICPC Asia Regional Dalian Online HDU 5877 Weak Pair treap + dfs序

Weak Pair 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 no

hdu 5877 Weak Pair(Treap平衡树 + dfs)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5877 题意:在一棵树上,每个节点有一个数值,问有多少对节点满足条件. 对于一对节点(u, v), 若满足 u 为 v的祖先节点且u,v节点上的数值乘积小于 k. 思路: dfs遍历树,对于每个节点 i 查询其祖先节点中,有多少个节点的值小于等于 k / ai(ai为当前节点的数值). dfs过程中,动态把祖先节点插入treap树中,退栈时删除. 1 #include <iostream> 2 #i

HDU 5877 Weak Pair(树状数组+dfs+离散化)

http://acm.hdu.edu.cn/showproblem.php?pid=5877 题意: 给出一棵树,每个顶点都有权值,现在要你找出满足要求的点对(u,v)数,u是v的祖先并且a[u]*a[v]<=k. 思路: 转化一下,a[v]<=k/a[u],k/a[u]的最大值也就是k/a[v],也就是寻找<=k/a[v]的个数,到这儿,是不是很像树状数组? 我们只需要从根开始dfs,插入到树状数组中,并且查询即可.注意这道题目需要离散化一下. 1 #include <iostr

HDU 5877 Weak Pair DFS + 树状数组 + 其实不用离散化

http://acm.hdu.edu.cn/listproblem.php?vol=49 给定一颗树,然后对于每一个节点,找到它的任何一个祖先u,如果num[u] * num[v] <= k.则贡献加1 思路:主要的麻烦就是动态修改前缀和了.因为对于每个数字val.则找它祖先的话, <= k / val的数字,都是合法的.所以问题转化成求你现在dfs中保存的数字,有多少个是  <= k / val的,树状数组即可. 问题就是,数字太大了,这不适合树状数组,那么我们把每个数字离散成他们的下

HDU 5877 dfs+ 线段树(或+树状树组)

1.HDU 5877  Weak Pair 2.总结:有多种做法,这里写了dfs+线段树(或+树状树组),还可用主席树或平衡树,但还不会这两个 3.思路:利用dfs遍历子节点,同时对于每个子节点au,查询它有多少个祖先av满足av<=k/au. (1)dfs+线段树 #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm>

hdu 5877 线段树(2016 ACM/ICPC Asia Regional Dalian Online)

Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 439    Accepted Submission(s): 155 Problem Description You are given a rooted tree of N nodes, labeled from 1 to N. To the ith node a