1 条题解

  • 2
    @ 2021-8-30 7:37:21

    从网上学了一个有意思的算法。改了一下,逻辑更简单一些。上来先用"左-根-右"的顺序深度遍历整个🌲,按照达到根的顺序输出根的值到一个数列,同时记录每个以此为根的🌲的节点数。最后找一下这个数列里面最长的回文数子数列。找回文数用马拉车的算法,这个算法会直接给出数列上面每个点为中心的最长回文数列长度。最后如果判断每个位置上对应的🌲的节点数是不是<=最长回文数列长度,如果yes这个紫薯就是对称的。

    #include <bits/stdc++.h>
    using namespace std;
    struct nodes {
        int value, left, right;
    } node[1000005];
    int res = 0, n, a[1000005], a_index = 0, cnt[1000005];
    inline int read() {
        int x = 0, f = 1;
        char ch = getchar();
        while (!isdigit(ch)) {if (ch == '-')f = -1; ch = getchar();}
        while (isdigit(ch)) {x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar();}
        return x * f;
    }
    int dfs(int index, int depth) {
        int count = 0, this_index;
        if (node[index].left > 0) count = dfs(node[index].left, depth + 1);
        a[this_index = a_index++] = (depth << 10) + node[index].value;
        if (node[index].right > 0) count += dfs(node[index].right, depth + 1);
        return cnt[this_index] = count + 1;
    }
    int *manacher() {
        int *b, *p, mem_size = sizeof(int) * ((n << 1) + 5);
        b = (int *)malloc(mem_size); // b(2 * n + 5, 0), p(2 * n + 5, 0);
        p = (int *)malloc(mem_size);
        b[0] = -2; b[1] = -1; b[(n << 1) + 2] = -3;
        for (register int i = 0, j = 2; i < n; i ++, j += 2) 
            b[j] = a[i ], b[j + 1] = -1;
        register int c = 0, r = 0;
        for (register int i = 1; i <= n << 1; i++) {
            p[i] = (i < r ? min(r - i, p[( c << 1) - i]) : 0);
            while (b[i + p[i] + 1] == b[i - p[i] - 1]) p[i]++;
            if (i + p[i] > r) c = i, r = i + p[i];
        }
        return p;
    }
    int main() {
        n = read();
        for (register int i = 1; i <= n; i++) node[i].value = read();
        for (register int i = 1; i <= n; i++) 
            node[i].left = read(), node[i].right = read();
        dfs(1, 0);
        int *p = manacher();
        for (register int i = 0, j = 2; i < n; i++, j += 2) {
            if (cnt[i] <= p[j]) res = max(res, cnt[i]);
        }
        cout << res;
    }
    
    • 1

    信息

    ID
    986
    时间
    1000ms
    内存
    256MiB
    难度
    6
    标签
    递交数
    51
    已通过
    15
    上传者