杭电 3887 Counting Offspring
来源:互联网 发布:为什么从百度离职 知乎 编辑:程序博客网 时间:2024/06/06 07:44
根据上篇翻译的文章以及很多个帖子,都讲述了树状数组最基本的功能就是tree[i]保存的是位置i左边小于等于a[i]的数的个数.
这样也就可以解释代码中为什么有f[i]=getsum(sd[i-1])-getsum(st[i]))/2。因为getsum保存的就是左边比i小的数,注意因为序列是通过dfs求出的,因而每个节点都有进入和退出过程,也就是每个节点都出现了2次,比如说对于数4来说,有4个节点,假设3为顶点,边的关系是3-2-1,3-2-4,那么dfs扫描出的序列就是3,2,1,1,4,4,2,3.所以求出的最终结果就需要除以2,因为每个数字都出现了2次。
至于为什么是从n-->1,我也纠结了半天,后来总算是YY出了一点思路【也可能不对】,因为已经将tree初始过了,考虑最原始的BIT,我们是一边遍历原始数组,一边getsum,一边update树,更新时,tree[i]+=1,这里提前将tree update过了,那么只能从后向前走,update(-1)了。假定最后一个点是n,那么在考虑其他节点的时候是不需要考虑这个点的,因为任何一个点都比最后这个点小,所以。。。update的时候是(-1)。
代码中注释的部分是原作者的,为了证实一下我自己YY出的结果是否正确,我测试了一下,果然A掉了。所以我的想法应该是对的,如果从头开始的话,需要从头遍历数组,得结果的时候需要两次update(1),这样的话仅仅需要从1-->就可以了。
代码如下:
#pragma comment(linker,"/STACK:100000000,100000000")#include <iostream>#include <cstdio>#include <algorithm>#include <vector>#include <cstring>using namespace std;const int maxn=100005;vector<int>vt[maxn];int bit[2*maxn];int que[2*maxn];int st[maxn];int sd[maxn];int f[maxn];int n, rt, num;void dfs(int u, int fa){ que[++num]=u; for(int i=0; i<vt[u].size(); i++) { int v=vt[u][i]; if(v==fa) continue; dfs(v,u); } que[++num]=u;}int lowbit(int x){ return x&(-x);}void update(int x, int val){ while(x<=num) { bit[x]+=val; x+=lowbit(x); }}int getsum(int x){ int ans=0; while(x>0) { ans+=bit[x]; x-=lowbit(x); } return ans;}int main(){//int a=4,b=3;//printf("%d",a|b); while(~scanf("%d%d",&n,&rt),n+rt) { for(int i=0; i<=n; i++) vt[i].clear(); for(int i=1; i<n; i++) { int x, y; scanf("%d%d",&x,&y); vt[x].push_back(y); vt[y].push_back(x); } fill(st+1,st+1+n,0); num=0; dfs(rt,-1);//每个节点开始和结束的位置 for(int i=1; i<=num; i++) { if(!st[que[i]])st[que[i]]=i; else sd[que[i]]=i; } memset(bit,0,sizeof(bit));/* for(int i=1; i<=num; i++) update(i,1); for(int i=n; i>=1; i--) { f[i]=(getsum(sd[i]-1)-getsum(st[i]))/2; update(st[i],-1); update(sd[i],-1); }*/for(int i=1;i<=n;i++)//这里是测试从1-->n的,注意对比{update(st[i],1);update(sd[i],1);f[i]=(getsum(sd[i]-1)-getsum(st[i]))/2;} printf("%d",f[1]); for(int i=2; i<=n; i++) printf(" %d",f[i]); puts(""); } return 0;}
- 杭电 3887 Counting Offspring
- hdu 3887 Counting Offspring
- HDU 3887 Counting Offspring
- hdu 3887 Counting Offspring
- HDU 3887 Counting Offspring 树状数组
- HDU 3887 Counting Offspring (树状数组)
- hdu3887 Counting Offspring
- Counting Offspring(hdu3887)
- Counting Offspring(hdu3887)
- Counting Offspring(hdu3887)
- Counting Offspring(hdu3887)
- Counting Offspring(hdu3887)
- HDU3887 Counting Offspring
- HDU 3887 Counting Offspring 树状数组 + 栈模拟dfs
- HDU 3887 Counting Offspring dfs序的运用 | 非递归
- HDU 3887 Counting Offspring(dfs序的应用)
- HDU 3887 Counting Offspring (DFS + BIT或划分树)
- HDU ACM 3887 Counting Offspring 树状数组+DFS
- PHPCMS problems set
- Win32设置窗口不可拖动,不能改变大小方法
- eclipse反编译插件jad
- 给而立之年纯为兴趣的IT爱好者提建议
- 基于B/S模式的推送
- 杭电 3887 Counting Offspring
- C++中如何建立一个顺序表
- DB_DOMAIN的一点知识
- 使用过滤器为每个页面加一个公用的尾部
- 黑马程序员_异常
- 黑马程序员_枚举
- 张江男曲折的出国梦
- 调用支付宝接口
- 关于内存的思考