两个二叉树的问题

版权声明:All rights reserved. https://blog.csdn.net/qq_42814118/article/details/81369939

问题一

一个以1为根的带权二叉树,每个点都有个权值 v i

  • 若点 b a 的左子树中,且 a b 的距离为 v b ,则称 b a 的左关联点

  • 若点 b a 的右子树中,且 a b 的距离为 v b ,则称 b a 的右关联点

求每一个点的左右关联点个数。
倍增快速跳即可,代码如下:

#include <bits/stdc++.h>

using namespace std;

#define R register
#define Maxn 1000005

int n,v[Maxn],lson[Maxn],rson[Maxn];
int f[Maxn][20],ans[Maxn][2];

template <class RME> inline void read(R RME &x)
{
    x=0;R bool f=0;R char ch;
    for(ch=getchar();ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=1;
    for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+(ch^48);
    if(f) x=-x; 
}

int main()
{
    read(n);
    for (R int i=1;i<=n;++i) read(v[i]);
    for (R int i=1;i<=n;++i) read(lson[i]),read(rson[i]),f[lson[i]][0]=f[rson[i]][0]=i;
    f[0][0]=0;
     for (R int j=1;j<=18;++j)
        for (R int i=1;i<=n;++i)
      {
          f[i][j] = f[f[i][j-1]][j-1];
      }
    for (R int i=1;i<=n;++i)
    {
        R int now=i;
        for (R int j=0;(1<<j)<=v[i]-1;++j)if((v[i]-1)&(1<<j)) now = f[now][j];
        R int fa=f[now][0];
        if(now==lson[fa]) ans[fa][0]++;
        else if(now==rson[fa]) ans[fa][1]++; 
    }
    for (R int i=1;i<=n;++i) printf("%d %d\n",ans[i][0],ans[i][1]);
    return 0;
}

问题二

问题一中的 v b 全部替换成 v a .。
简单推一下即可,不会爆栈。
代码如下:

#include <bits/stdc++.h>

using namespace std;

#define R register
#define Maxn 1000005

int tesc;
int next_int()
{
    register char ch;
    while(ch = getchar(), ch < '0' || ch > '9') ;
    register int ans = ch - '0';
    while(ch = getchar(), '0' <= ch && ch <= '9') ans = ans * 10 + ch - '0';
    return ans;
}
int n,v[Maxn],lson[Maxn],rson[Maxn],dep[Maxn],cnt[Maxn],ans[Maxn][2];
void dfs(R int pos)
{
    cnt[dep[pos]] ++;
    if(lson[pos])
    {
        dep[lson[pos]] = dep[pos] + 1;
        R int tmp = cnt[dep[pos]+v[pos]];
        dfs(lson[pos]);
        ans[pos][0] = cnt[dep[pos]+v[pos]]-tmp;
    }
    if(rson[pos])
    {
        dep[rson[pos]] = dep[pos] + 1;
        R int tmp = cnt[dep[pos]+v[pos]];
        dfs(rson[pos]);
        ans[pos][1] = cnt[dep[pos]+v[pos]] - tmp;
    }
}
int main()
{
    freopen("test.in","r",stdin);
    /*
    int size = 64 << 20;  
    char *p = (char*)malloc(size) + size;  
    __asm__("movl %0, %%esp\n" :: "r"(p));  
    */
    n = next_int();
    for(register int i = 1; i <= n; ++i) v[i] = next_int();
    for(register int i = 1; i <= n; ++i) lson[i] = next_int(), rson[i] = next_int();
    dfs(1); 
    R const int P = 1004535809, Q = 998244353;
    R int A = 2341, B = 4123;
    for(register int i = 1; i <= n; ++i)
    {
        A = ((long long) A * n + ans[i][0]) % P; B = ((long long) B * n + ans[i][0]) % Q;
        A = ((long long) A * n + ans[i][1]) % P; B = ((long long) B * n + ans[i][1]) % Q;
    }
    printf("%d %d\n",A,B);
    return 0;
}

血的教训:
倍增注意for的顺序,先for0-32!

for (R int j=1;j<=18;++j)
        for (R int i=1;i<=n;++i)
      {
          f[i][j] = f[f[i][j-1]][j-1];
      }

就这玩意儿调了我一晚上。。

猜你喜欢

转载自blog.csdn.net/qq_42814118/article/details/81369939