[题解]P1087 FBI树

· · 题解

题目传送门

看到这道题,我的脑子中蹦出来了一个毒瘤想法,此题为线段树树的遍历

可能太毒瘤了,机房高二学长一直在想如何hack掉我的代码

(如果有大佬能hack掉我的代码,请私信我,把数据发过来,谢谢}

首先,很明显,此题字符串的处理运用了二分的思想

很像线段树不是吗?

所以就有了建树方法


inline void pushup(int now){
    if(tree[ls]=='F'||tree[rs]=='F'){ tree[now]='F'; return;}
    if(tree[ls]==tree[rs]){ tree[now]=tree[ls]; return;}
    tree[now]='F';
}

inline void build(int now,int l,int r){
    if(l==r){ tree[now]=(a[l]?'I':'B'); return; }
    rg int mid=(l+r)>>1;

    build(ls,l,mid);
    build(rs,mid+1,r);

    pushup(now);
}

各位可以自行脑补一下

如果一个节点的两个子节点有一个是F,那么这个节点肯定是F

如果一个节点的两个子节点相同,那么这个节点肯定与他的左节点(或右节点)相同

否则这个节点一定是F

具体思路就不再详细讲解了,直接上代码吧


inline void dfs(int now){
    if(!tree[now]) return;
    if((!tree[ls])&&(!tree[rs])){ putchar(tree[now]); return; }

    dfs(ls);
    dfs(rs);

    putchar(tree[now]);
}
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<stack>
#include<string>
#include<queue>
#include<vector>
#include<map>
#include<deque>
#include<bitset>
#include<set>

using namespace std;

#define ll long long
#define ull unsigned long long
#define rg register

inline int read(){
    rg int s=0,f=0;
    rg char ch=getchar();

    while(not isdigit(ch)) f|=(ch=='-'),ch=getchar();
    while(isdigit(ch)) s=(s<<1)+(s<<3)+(ch^48),ch=getchar();

    return f?-s:s;
}

const int CSP_S=2019;
int n,a[CSP_S];
char tree[CSP_S<<2];

#define ls (now<<1)
#define rs (now<<1|1)

inline void pushup(int now){
    if(tree[ls]=='F'||tree[rs]=='F'){ tree[now]='F'; return;}
    if(tree[ls]==tree[rs]){ tree[now]=tree[ls]; return;}
    tree[now]='F';
}

inline void build(int now,int l,int r){
    if(l==r){ tree[now]=(a[l]?'I':'B'); return; }
    rg int mid=(l+r)>>1;

    build(ls,l,mid);
    build(rs,mid+1,r);

    pushup(now);
}

inline void dfs(int now){
    if(!tree[now]) return;
    if((!tree[ls])&&(!tree[rs])){ putchar(tree[now]); return; }

    dfs(ls);
    dfs(rs);

    putchar(tree[now]);
}

signed main(){
//  freopen("test.txt","w",stdout);
    n=read();
    getchar();
//  快读选手在洛谷IDE及洛谷评测必须加此行,否则当场去世(原因过于神奇)
    for(rg int i=1;i<=(1<<n);i=-~i) a[i]=getchar()=='0'?0:1;

    build(1,1,(1<<n));

    dfs(1);

   return 0;
}

我的博客 USSENTERPRISE的博客