Educational Codeforces Round 127 (Rated for Div. 2)

Educational Codeforces Round 127 (Rated for Div. 2)

E. Preorder

题意:给一颗点权仅为AB的完全二叉树,可以对每个点的两个子树进行交换,求前序遍历共有多少种
做法:其实很好想,设dp[x],表示以x为子树的方案有多少种,那么假如两棵子树完全一样,\(dp[x]=dp[l]*dp[r]\),但是两棵子树不一样,那么交换后还会产生\(dp[l]*dp[r]\),即\(dp[x]=2*dp[l]*dp[r]\),所以只需要判断两棵子树是否本质相同就可以了,判断方法可以暴力,因为所有子树的大小和是nlogn的,也可以采用树hash,但是要注意题目后来补充The operation swaps the whole subtrees of two children of the vertex, not just the characters on these children.,所以交换是只能交换两个子树,并不是两个子节点,

点击查看代码
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn=1<<19;
const ll mod=998244353;

ll dp[maxn];
int a[maxn];
char s[maxn];
int N;

string dfs(int x){
    if(x*2>N){
        dp[x]=1;
        string p="";
        return p+s[x];
    }
    int l=x*2;
    int r=x*2+1;
    //if(s[l]>s[r]) swap(s[l],s[r]);
    string p1=dfs(l);
    string p2=dfs(r);
    if(p1==p2) dp[x]=dp[l]*dp[r]%mod;
    else dp[x]=dp[l]*dp[r]*2ll%mod;
    if(p1>p2) swap(p1,p2);
    return s[x]+p1+p2;
}

int main(){
    int n;
    cin>>n;
    N=(1<<n)-1;
    scanf("%s",s+1);
    dfs(1);
    printf("%lld\n",dp[1]%mod);
    return 0;
}
posted @ 2022-04-25 20:00  lmj_1  阅读(47)  评论(0)    收藏  举报