这道题。。。。。。 本蒟蒻用暴力+输入输出优化+inline卡时间勉强AC 我的思路很简单,从根开始依次往下遍历,找最大值 注意题目描述:::
本题中约定,以节点 TT 为子树根的一棵“子 树”指的是:节点TT 和它的全部后代节点构成的二叉树
所以只需要check一遍判断就好了 我的代码很复杂 首先来看输入输出优化 输入优化:
inline void sc(int &x) {//读入要改变x的值
x=0;int f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}//判断正负
while(s>='0'&&s<='9'){x=x*10+s-48;s=getchar();}//读入
x*=f;//稍微学过一点的都应该看得懂。。。
}
输出优化:
inline void pr(int x) {
if(x<0)putchar('-'),x=-x;//负数
if(x>9)pr(x/10);//用递归从前往后输出
putchar(x%10+48);//输出
}
以上两段代码都是利用c++输入输出字符比数字快的原理 然后来看主程序:
int main() {
sc(n);
for(int i=1;i<=n;i++)
sc(a[i].v);
for(int i=1;i<=n;i++)
sc(a[i].l),sc(a[i].r);
dfs(1);
pr(ans);
}
再来看dfs:
inline void dfs(int x) {//从根节点开始搜
tot=3;
if(a[x].l==-1&&a[x].r==-1)//左右儿子都是-1
ans=max(ans,1),tot=3;//判断,tot=3在代码后面解释
else if(a[x].l!=-1&&a[x].r!=-1)//左右儿子都不是-1
if(check(a[x].l,a[x].r))//判断是不是一棵对称二叉树
ans=max(ans,tot),tot=3;
if(a[a[x].l].v!=a[a[x].r].v||a[x].l==-1||a[x].r==-1||!check(a[x].l,a[x].r)) {//在权值不等或一边没有或不是对称二叉树的情况下,要两边分别搜
if(a[x].l!=-1)//左边有值搜左边
dfs(a[x].l);
tot=3;
if(a[x].r!=-1)//右边有值搜右边
dfs(a[x].r);
}
tot=3;
}
/*
此处的inline可以减少函数调用的时间
*/
tot=3是因为如果能进check的话就至少有三个。 其中根为一个,左右儿子有两个 因为在check里面没打,所以就这样了 接下来是check:
inline bool check(int x,int y) {//我判断得很复杂,大家可以想想怎么改进
if(x==-1&&y==-1) return 1;
else if(a[x].v!=a[y].v){tot=0;return 0;}
else if((a[x].l==-1&&a[y].r!=-1)||(a[x].l!=-1&&a[y].r==-1)||(a[x].r==-1&&a[y].l!=-1)||(a[x].r!=-1&&a[y].l==-1)){tot=3;return 0;}
else if(a[x].l!=-1&&a[y].r!=-1&&a[x].r!=-1&&a[y].l!=-1&&check(a[x].l,a[y].r)&&check(a[x].r,a[y].l)){tot+=4;return 1;}
else if(a[x].l==-1&&a[y].r==-1&&a[x].r!=-1&&a[y].l!=-1&&check(a[x].r,a[y].l)){tot+=2;return 1;}
else if(a[x].r==-1&&a[y].l==-1&&a[x].l!=-1&&a[y].r!=-1&&check(a[x].l,a[y].r)){tot+=2;return 1;}
else if(a[x].l==-1&&a[x].r==-1&&a[y].l==-1&&a[y].r==-1)return 1;
return check(a[x].l,a[y].r)&&check(a[x].r,a[y].l);
}
/*
第一个if是判断如果没有儿子就return
第一个else if是判断两边权值不相等就不成立
第二个else if是判断儿子对不对称,不对称就不成立
第三个else if是判断两个点都有儿子且儿子对称,要加4个点
第四个else if是判断x的左儿子和y的右儿子对不对称,要加2个点
第五个else if是判断x的右儿子和y的左儿子对不对称,要加2个点
最后一个else if是判断如果两个点都没有儿子,树也是成立的
最后就是判断
*/
是不是超复杂。。。。。。 下面是完整代码
#include
inline void sc(int &x) {
x=0;int f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-48;s=getchar();}
x*=f;
}
inline void pr(int x) {
if(x<0)putchar('-'),x=-x;
if(x>9)pr(x/10);
putchar(x%10+48);
}
inline int max(int x,int y) {
return x>y?x:y;
}
struct node {
int l,r,v;
}a[1000005];
int n,k,ans=1,tot=3;
inline bool check(int x,int y) {
if(x==-1&&y==-1) return 1;
else if(a[x].v!=a[y].v){tot=0;return 0;}
else if((a[x].l==-1&&a[y].r!=-1)||(a[x].l!=-1&&a[y].r==-1)||(a[x].r==-1&&a[y].l!=-1)||(a[x].r!=-1&&a[y].l==-1)){tot=3;return 0;}
else if(a[x].l!=-1&&a[y].r!=-1&&a[x].r!=-1&&a[y].l!=-1&&check(a[x].l,a[y].r)&&check(a[x].r,a[y].l)){tot+=4;return 1;}
else if(a[x].l==-1&&a[y].r==-1&&a[x].r!=-1&&a[y].l!=-1&&check(a[x].r,a[y].l)){tot+=2;return 1;}
else if(a[x].r==-1&&a[y].l==-1&&a[x].l!=-1&&a[y].r!=-1&&check(a[x].l,a[y].r)){tot+=2;return 1;}
else if(a[x].l==-1&&a[x].r==-1&&a[y].l==-1&&a[y].r==-1)return 1;
return check(a[x].l,a[y].r)&&check(a[x].r,a[y].l);
}
inline void dfs(int x) {
tot=3;
if(a[x].l==-1&&a[x].r==-1)
ans=max(ans,1),tot=3;
else if(a[x].l!=-1&&a[x].r!=-1)
if(check(a[x].l,a[x].r))
ans=max(ans,tot),tot=3;
if(a[a[x].l].v!=a[a[x].r].v||a[x].l==-1||a[x].r==-1||!check(a[x].l,a[x].r)) {
if(a[x].l!=-1)
dfs(a[x].l);
tot=3;
if(a[x].r!=-1)
dfs(a[x].r);
}
tot=3;
}
int main() {
sc(n);
for(int i=1;i<=n;i++)
sc(a[i].v);
for(int i=1;i<=n;i++)
sc(a[i].l),sc(a[i].r);
dfs(1);
pr(ans);
}
大概用时670ms左右