HDU 3887 Counting Offspring dfs序的运用 | 非递归
来源:互联网 发布:js鼠标跟随特效 花瓣 编辑:程序博客网 时间:2024/05/20 11:52
题目链接
一天时间做了两道 dfs序 的题, 都是 WA 不停,最后一道改成 100W的数组,一道改成双向边就AC了。。能不能再坑一点的。。
好,继续说这道题。。
上一道题苹果树是统计叶子节点的和,这道题是统计叶子节点中比自己权值小的和
思路
首先按照上一道题的惯性思路,会觉得很复杂。因为再算和的时候要额外判断一下大小。由于树状数组是预处理的,显然无法再单独判断,于是就不知如何是好。
后来想到,能不能在 dfs 中记录一下比自己小的数。
如何统计?
第一会想到 DP 一样的东西,如果比子节点大,直接加上,如果小的话,貌似跪了。。。
突然想到以前有过一次 在树状数组的建树过程中动态维护区间和,觉得可以试试。
于是就有了这样的算法:
在dfs过程中,第一次(也是唯一一次)碰到一个点 v 时, visit[i] = 1. 此时,pre[v] = visit[0,v) 的和也就是比v小的数的个数!因为 dfs序的性质,现在计算的和是不含它的子节点的,当一个点dfs过后,再计算一下s = visit[0,v) 的和,它表示的便是包含子节点在内的所有比 v 小的点的和。因为dfs序的性质,s[v]-pre[v] 便是子节点中比自己小的点的权值的和。
有木有发现,其实连进出的时间戳都没有记录!只是在进出栈时就把ans计算出来了。
另外比较坑的就是如果用 递归写法会耗费很多堆栈,不得已改用非递归写法。
上代码:
#include <cstdio>#include <stack>#define N 201010using namespace std;stack<int> st;struct NODE { int v,next;} a[N],e[N];int tr[N],pre[N],s[N],b[N];int n,em,root,tt;void update(int x) { while ( x<=n) { tr[x] += 1; x += x & -x; }}int gs(int x) { int s = 0; while (x>0) { s += tr[x]; x -= x & -x; } return s;}void joint(int a1,int a2){ e[++em].v = a2; e[em].next = a[a1].next; a[a1].next = em;}int main() { while ( ~scanf("%d%d",&n,&root)) { if ( !n && !root ) break; for ( int i(1); i<=n; i++) tr[i] = a[i].next = b[i] = pre[i]= 0; em = 0; tt = 0; for ( int i(1); i<n; i++) { int a1,a2; scanf("%d%d",&a1,&a2); joint(a1,a2); joint(a2,a1); } while (!st.empty()) st.pop(); // dfs st.push(root); while (!st.empty()) { int v = st.top(); if ( !b[v] ){ b[v] = 1; pre[v] = gs(v); update(v); for ( int p(a[v].next); p; p=e[p].next) { if ( !b[e[p].v] ) { int u = e[p].v; st.push(u); } } } if ( st.top() == v ) { s[v] = gs(v-1) - pre[v]; st.pop(); } } for ( int i(1); i<n; i++) printf("%d ",s[i]); printf("%d\n",s[n]); } return 0;}
0 0
- HDU 3887 Counting Offspring dfs序的运用 | 非递归
- HDU 3887 Counting Offspring(dfs序的应用)
- HDU 3887 Counting Offspring(dfs序 + 树状数组)
- HDU-3887-Counting Offspring-dfs序+树状数组
- HDU 3887 Counting Offspring(dfs序+树状数组)
- hdu 3887 Counting Offspring(dfs序+树状数组)
- hdu 3887 Counting Offspring
- HDU 3887 Counting Offspring
- hdu 3887 Counting Offspring
- HDU3887 Counting Offspring【dfs序】
- HDU 3887 Counting Offspring 树状数组 + 栈模拟dfs
- HDU 3887 Counting Offspring (DFS + BIT或划分树)
- HDU ACM 3887 Counting Offspring 树状数组+DFS
- hdu 3887 Counting Offspring dfs 树 树状数组
- HDU 3887 Counting Offspring (树状数组+dfs)
- 【HDU 3887】【dfs序+线段树】Counting Offspring 【查询子树上标号比它小的点有多少个 】
- HDU 3887 Counting Offspring(DFS序求子树权值和)
- hdu3887 Counting Offspring(dfs序+树状数组)
- JSP标签c:forEach报错(二)
- vdr使用linux nfs作为存储
- PHP array_combine() 函数,合并两个数组来创建一个新数组
- Rational Rose 之 计算机丢失suite objects.dll
- C# List的一些LINQ用法
- HDU 3887 Counting Offspring dfs序的运用 | 非递归
- 重新扬帆启航
- 【暴力几何】#6 A. Triangle
- 十大将拯救地球的开源硬件项目llllll
- 区分Activity的四种加载模式
- CUDA编程接口:异步并发执行的概念和API
- (虚)继承类的内存大小计算
- OpenCV中Canny()“自适应”算法的分割阈值
- C++中的位运算