树状数组 + 离散化 + dfs HDU 5877
来源:互联网 发布:2016域名价格排行榜 编辑:程序博客网 时间:2024/05/21 18:00
Weak Pair
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 3893 Accepted Submission(s): 1165
(1)
(2)
Can you find the number of weak pairs in the tree?
The first line of input contains an integer
For each case, the first line contains two space-separated integers,
The second line contains
Each of the subsequent lines contains two space-separated integers defining an edge connecting nodes
Constrains:
12 31 21 2
1. u 节点是 v 节点的祖先节点
2. a[u] * a[v] <= k
求这棵树满足条件的对子数
思路:首先观察题目的两个条件,第一个 u 是 v 的祖先节点,那么也就是说 要从上往下考虑,但是你会发现,不行啊,从上往下,我的兄弟节点不是我的祖先节点啊,可是他会在我前面出现,也会在我后面,那怎么办呢,想一下,你从此节点,向上找祖先节点的时候,发现,它是一条直线往上的,并且只有一条路径,因为每个节点的父亲只有一个,那就好办了,这不就是 dfs序吗,但 dfs 序是先从根节点开始,从上往下的,没关系,先让它从上往下搜,搜到叶子节点的时候,这条dfs路径上经过的点,不正好全都是这个叶子节点的祖先节点吗?,那就好办了,就dfs的时候一边计数,到达叶子节点之后就计算一下,然后返回的时候删掉叶子节点的贡献,返回去继续计数,妥妥的。
用一个图直观地看看吧
详细作法:首先考虑到题目给的节点的值会非常的大,要把这些值update到树状数组里的前提条件是开的了那么大的数组,显然不行,又注意到点的个数不超过 10^5 个,所以实际上并没有那么多的数值,所以可以离散化来处理
这里介绍一个比较方便的离散化方法,用到 unique()函数 ,它是去重算法,可以把相邻的相同的数刨去,然后返回剩余数值个数,所以我们先 sort 排序一下输入的值,然后用这个东西就能把数值转化为 1 到 cnt 的数了
void discre(){ // 离散化 sort(tm + 1,tm + 1 + n);cnt = unique(tm + 1,tm + 1 + n) - tm - 1;}
然后我们找到根节点,从根节点开始进行 dfs,然后使用upper_bound() 函数,它是用来找到某个数组里某个值第一次出现的下标的,拿它到 unique 处理过的 tm[] 数组里找 当前节点的值 a[x] 的下标,就可以拿这个下标的值来代替原本的值,这里就实现了离散化。找到这个值后,把它 update 进树状数组,然后对儿子节点继续 dfs ,直到叶子节点的时候 ,把自身的值从树状数组里刨去,然后 要是 a[x] * a[v] <= k ,也就是要找到 小于等于 k / a[x] 的值 tmp
if(a[x] == 0)tmp = tm[cnt] + 1;// a[u] * a[v] <= k 当 a[u] = 0的时候,全部都满足,所以给它一个最大值 + 1 elsetmp = k / a[x];// 否则就 k / a[x] 找到最大的满足的值,然后在这个值之前都是满足的 if(tmp > tm[cnt])tmp = tm[cnt] + 1;
这里分情况 : 当 a[x] = 0 的时候,所有的情况都符合,所以再大的值也可以满足条件,所以要给 tmp 一个足够大的值,前面 tm数组里 tm[cnt]是最大的值,所以 让 tmp = tm[cnt] + 1就可以了, 然后 upper_bound()找tmp值找不到就会返回 end()尾指针,也就是最大的了,然后到树状数组里查询就可以了,树状数组记录的是前缀和,所以直接查询 tmp 就可以得到比它小的值的个数,这个个数就是计数要找的
#include<cstdio>#include<iostream>#include<algorithm>#include<vector>#include<cmath>#include<cstring>using namespace std;#define ll long long#define mem(a,x) memset(a,x,sizeof(a))#define lowbit(x) (x & (-x))#define maxn 110005ll n,tm[maxn],tree[maxn],a[maxn],k,ans,cnt,dep[maxn];vector<int>vec[maxn];void update(int x,int v){while(x <= n){tree[x] += v;x += lowbit(x);}}ll getSum(int x){ll tmp = 0;while(x){tmp += tree[x];x -= lowbit(x);}return tmp;}int find(ll x){return upper_bound(tm + 1,tm + 1 + cnt,x) - tm - 1; // 找到第一个该值的点的下标}void dfs(int x){update(find(a[x]),1);// 把值离散化为小值之后放进树状数组 int len = vec[x].size();for(int i = 0;i < len;i++){dfs(vec[x][i]);}update(find(a[x]),-1); //本节点是处理到的最尾节点了,把值去掉 ll tmp;if(a[x] == 0)tmp = tm[cnt] + 1;// a[u] * a[v] <= k 当 a[u] = 0的时候,全部都满足,所以给它一个最大值 + 1 elsetmp = k / a[x];// 否则就 k / a[x] 找到最大的满足的值,然后在这个值之前都是满足的 if(tmp > tm[cnt])tmp = tm[cnt] + 1;ans += getSum(find(tmp));} void discre(){ // 离散化 sort(tm + 1,tm + 1 + n);cnt = unique(tm + 1,tm + 1 + n) - tm - 1;}void init(){mem(dep,0);mem(tree,0);mem(vec,0);}int main(){int u,v,t;scanf("%d",&t);while(t--){ans = 0;scanf("%lld %lld",&n,&k);for(int i = 1;i <= n;i++){scanf("%lld",&a[i]);tm[i] = a[i];}discre(); //离散化 init();for(int i = 1;i < n;i++){scanf("%d %d",&u,&v);vec[u].push_back(v);dep[v]++;//深度 }for(int i = 1;i <= n;i++){if(dep[i] == 0){dfs(i); //找到根节点 dfs break;}}printf("%lld\n",ans);}return 0;}
- hdu 5877 dfs+离散化+树状数组
- 树状数组 + 离散化 + dfs HDU 5877
- DFS+离散+树状数组 +细节 HDU 5877
- HDU 5877 Weak Pair(dfs + 树状数组 + 离散化)
- HDU 5877 dfs+离散化+树状数组(树上维护)
- hdu 5877 离散化+树状数组+dfs序
- HDU 5877(Problem 1010) (DFS+树状数组+离散化)
- hdu 5877 Weak Pair(树状数组 + dfs + 离散化)
- HDU 5877 Weak Pair 【dfs】【树状数组】【离散化】
- HDU 5877 Weak Pair dfs序 + 树状数组 + 离散化
- hdu 5877 树状数组 +离散化 +树
- hdu 5877(树状数组+离散化)
- 2016 大连网络赛 HDU 5877 Weak Pair (DFS + 树状数组 + 离散化)
- HDU-5877-Weak Pair【树状数组】【离散化】【DFS】【2016大连网络】【好题】
- HDU 5877 Weak Pair(离散化+dfs+树状数组) 大连区域网络赛
- hdu4605 树状数组+离散化+dfs
- HDU 5877 Weak Pair(离散化+dfs+树状数组)——2016 ACM/ICPC Asia Regional Dalian Online
- hdu 5877 Weak Pair 树状数组+离散化
- ztree一级一级加载数据
- Java (运算符,优先级)
- [Struts2] 国际化
- 51单片机和HC05蓝牙模块对接成功,但是数据收发时候发现数据很多时候对不上问题解决
- 迈进算法的大门
- 树状数组 + 离散化 + dfs HDU 5877
- opencv交叉编译arm环境库,静态,动态库和可执行程序
- 虚拟机无法联网的解决办法
- [Struts2] 拦截器和过滤器
- mustache 渲染列表项 index
- java实训第一节
- 堆排序
- [Struts2] 配置Struts可以受理的请求的扩展名
- 由一道题了解Happens