您的位置:首页 > 其它

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

2015-11-01 10:14 471 查看



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.(1≤N≤1018)
 

Output

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

Sample Input

5
6
7
8

 

Sample Output

3
4
3
5

 

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|1
typedef 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))

【数据】
input
1000000000000000000

output
118

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ACM 算法 脑洞