在考场上的玄学思路:
这道题的思路相对来说还是很好想出来的(
首先,对于每一个节点,只要右儿子节点与左儿子节点的权值不同,就肯定不是对称的,舍去
然后,每一次向下走一层的时候,左子树跟右子树的路径取反
什么意思呢?
就是,你左子树向右走,右子树就向左走;左子树向左走,右子树向右走
(如果这里不能理解建议动手画图看一下)
同理,判断时也取反
分四种情况:
-
如果左子树的根节点没有左子树而右子树的根节点有右子树,那么结构上肯定不满足对称性,舍去
-
如果左子树的根节点没有右子树而右子树的根节点有左子树,那么结构上肯定不满足对称性,舍去
-
如果左子树的根节点有左子树而右子树的根节点没有右子树,那么结构上肯定不满足对称性,舍去
-
如果左子树的根节点有右子树而右子树的根节点没有左子树,那么结构上肯定不满足对称性,舍去
那么什么时候满足对称性呢?
——当搜索到两个节点,两个节点同为叶子结点且权值相等时
但只要有其中某一条路径不满足,整颗子树肯定不满足
那么,按照以上思路打出来的代码是多少分的呢?我怎么知道
96分
用了一次下载数据的机会……(in luogu)
哦,炸了,极限数据卡成一条链了……
那么,我们还可以加上什么优化呢?
给大家3分钟的思考时间……
优化很简单——只要左右子树的节点数目不同,则结构肯定不对称!
那么这个优化加上去多少分?
当然AC啦!
上代码!喂喂喂音乐老师怎么回事BGM呢
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; struct note { int left; int right; int val; }; int n,ans; note a[1000010]; int d[1000010]; int fast_read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') { f=-1; } ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+ch-'0'; ch=getchar(); } return x*f; } int dfs(int root) { //printf("%d\n",root); if(a[root].left==-1&&a[root].right==-1) { return 1; } int s=1; if(a[root].left!=-1) { s+=dfs(a[root].left); } if(a[root].right!=-1) { s+=dfs(a[root].right); } d[root]=s; return s; } bool dfs2(int left,int right) { if(a[left].val!=a[right].val) { return 0; } if(a[left].left==-1) { if(a[right].right!=-1) { return 0; } } if(a[left].right!=-1) { if(a[right].left==-1) { return 0; } } if(a[left].left!=-1) { if(a[right].right==-1) { return 0; } } if(a[left].right==-1) { if(a[right].left!=-1) { return 0; } } if(a[left].right==-1&&a[left].left==-1) { return 1; } bool f=1; if(!dfs2(a[left].left,a[right].right)) { f=0; } if(!dfs2(a[left].right,a[right].left)) { f=0; } return f; } void work() { for(int i=1;i<=n;i++) { if(a[i].left!=-1&&a[i].right!=-1) { if(d[i]>ans&&d[a[i].left]==d[a[i].right]&&dfs2(a[i].left,a[i].right)) { ans=d[i]; } } else { ans=max(ans,1); } //printf("%d\n",ans); } } int main() { //freopen("testdata (2).in","r",stdin); n=fast_read(); for(int i=1;i<=n;i++) { a[i].val=fast_read(); d[i]=1; } for(int i=1;i<=n;i++) { a[i].left=fast_read(); a[i].right=fast_read(); } int k=dfs(1); work(); /* for(int i=1;i<=n;i++) { printf("%d\n",d[i]); } */ printf("%d\n",ans); return 0; }
各位,暴力出奇迹啊!