题目
题意: 给定一棵n个节点的完全二叉树的后序遍历(不一定满足是2^k-1,但是只会在右边缺点。n<=60)。给定m组查询,对于给定点x。判断是否在书中。若在树中,则将以它为根的子树全部标记上,并输出本次操作中标记的叶子的数量。若已经被标记,则输出一句奇奇怪怪的话。最后输出所有未被标记的点形成的前序遍历。
思路: 根据完全二叉树的特点建树即可,开个数组。递归的建树,先儿子,再根节点。
时间复杂度: O(m*logn + n) 根据给定的值拿map映射到在树中的下标,反正n很小,无所胃。
代码:
#include<bits/stdc++.h>
using namespace std;
#define mem(a,x) memset(a,x,sizeof(a))
#define fir(i,a,b) for(int i=a;i<=b;++i)
const int N = 1e5+10;
typedef long long ll;
typedef pair<int,int> PII;
int n,m,k,T;
int a[102];
int idx = 0;
int b[102];
bool vis[102];
map<int,int> mp;
void get(int now)
{
if(now > n)
{
return ;
}
get(now<<1|1);
get(now<<1);
//右、左、根
a[now] = b[idx++];
}
bool kong = true;
void pre(int now)
{
if(now > n || vis[now]) return;
if(kong)
printf("%d",a[now]),kong = false;
else printf(" %d",a[now]);
pre(now<<1);
pre(now<<1|1);
}
int mx;
int va[] = {1,3,7,15,31,63};
int dfs(int cur)
{
// cout<<cur<<"?"<<endl;
if(cur > n || vis[cur]) return 0;
vis[cur] = 1;
if(cur*2>mx) return 1;
return dfs(cur<<1)+dfs(cur<<1|1);
}
void solve()
{
cin>>n;
for(int i=0;;++i)
{
if(va[i] >= n)
{
mx = va[i];
break;
}
}
for(int i=0;i<n;++i)
{
cin>>b[i];
}
get(1);
for(int i=1;i<=n;++i) mp[a[i]] = i; //x在树中的下标位置
cin>>m;
while(m--)
{
int root; cin>>root;
root = mp[root];
if(root==0)
{
cout<<"Kan Qing Chu Le?\n";
}
else
{
if(vis[root])
{
cout<<"Zao Jiu Cai Diao Le!\n";
}
else
{
cout<<dfs(root)<<"\n";
}
}
}
int cnt = 0;
for(int i=1;i<=n;++i) if(vis[i]) cnt++;
if(cnt == n)
{
cout<<"Kong Le!";
}
else
{
pre(1);
}
}
signed main(void)
{
solve();
return 0;
}