【HDU5524 BC61 div1 B】【SET模拟】Subtrees 二叉树不同子节点树的子树个数

来源:互联网 发布:淘宝里怒吼的表情 编辑:程序博客网 时间:2024/04/29 08:02


Subtrees

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 102    Accepted Submission(s): 58


Problem Description
There is a complete binary tree with N nodes.The subtree of the node i has Ai nodes.How many distinct numbers are there of Ai?
 

Input
There are multiple test cases, no more than 1000 cases.
For each case contains a single integer N on a line.(1N1018)
 

Output
The output of each case will be a single integer on a line:the number of subtrees that contain different nodes.
 

Sample Input
5678
 

Sample Output
3435
 

Source
BestCoder Round #61 (div.2)
 

 
#include<stdio.h>#include<string.h>#include<ctype.h>#include<math.h>#include<iostream>#include<string>#include<set>#include<map>#include<vector>#include<queue>#include<bitset>#include<algorithm>#include<time.h>using namespace std;void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);}#define MS(x,y) memset(x,y,sizeof(x))#define MC(x,y) memcpy(x,y,sizeof(x))#define MP(x,y) make_pair(x,y)#define ls o<<1#define rs o<<1|1typedef long long LL;typedef unsigned long long UL;typedef unsigned int UI;template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;}template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;}const int N=0,M=0,Z=1e9+7,ms63=1061109567;int casenum,casei;LL b[70],s[70];set<LL>sot;LL n;int DEP;int ans;void init(){    for(int i=0;i<=60;i++)    {        b[i]=1ll<<i;        s[i]=b[i]*2-1;    }}void go(int dep,LL x,LL son){    sot.insert(son);    if(dep==0)return;    LL o=x-s[dep-1];//求出这个点是这层的第几个点    if(o!=1)//左面有    {        sot.insert(s[DEP-dep]);//有到叶子距离为DEP-dep的完全二叉树    }    if(o!=b[dep])//右面有    {        if(DEP-1-dep>=0)sot.insert(s[DEP-1-dep]);//有到叶子距离为DEP-1-dep的完全二叉树    }    if(x&1)//如果在右面    {        LL lson=s[DEP-dep];//左面有这么大一棵树        son+=lson+1;    }    else//如果在左面    {        LL rson=s[DEP-dep]>>1;//右面有这么大一棵树        son+=rson+1;    }    go(dep-1,x>>1,son);}int main(){    init();    while(~scanf("%lld",&n))    {        sot.clear();        for(DEP=0;s[DEP]<n;DEP++);//找到它所在的层次        go(DEP,n,1);        printf("%d\n",sot.size());    }    return 0;}/*【题意】给你一个恰好有n([1,1e18])节点的完全二叉树,问你这个二叉树有多少个子树节点数不同的节点。其中,完全二叉树的定义是:除了最后一层,其他层的节点都是满的。且最后一层的节点都是分布在最左侧。【类型】SET模拟【分析】模拟式的解题思维往往都是很有价值的。我们首先可以预处理出——深度恰好为dep的满二叉树的该层节点数以及总共节点数然后从关键点,也就是最后一个点开始,向上沿着链走,一直走到根节点。我们可以更新出,走到这个链上某个节点时的子节点数。现在有一个很好玩而且很有意义的性质,就是这个节点同层的左边的都是满二叉树,同层的右边的是少一深度的满二叉树。于是我们就把这3种子节点数插入set中。最后的set.size()就是答案【时间复杂度&&优化】O(log(n))【数据】input1000000000000000000output118*/


1 0
原创粉丝点击