답안 #532181

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
532181 2022-03-02T09:45:53 Z tibinyte Lampice (COCI19_lampice) C++14
0 / 110
5000 ms 16468 KB
#include <bits/stdc++.h>
using namespace std;
vector<int> centree[50001], g[50001];
bool color[50001], seen[50001], depth[50001];
int dp[50001], pater[50001], pater2[50001], power[50001], inv[50001], up[50001], down[50001], rmq[50001][18], n, p = 31, mod = 1000000007;
multiset<int> hashes[50001];
string s;
int powmod(int a, int b) {
    if (b == 0) {
        return 1;
    }
    if (b % 2 == 1) {
        return (1ll * a * powmod(a, b - 1));
    }
    int P = powmod(a, b / 2);
    return (P * P) % mod;
}
int invers(int a) {
    return powmod(a, mod - 2);
}
int get_size(int node, int parent) {
    if (seen[node]) {
        return 0;
    }
    dp[node] = 0;
    for (auto i : g[node]) {
        if (i != parent) {
            dp[node] += get_size(i, node);
        }
    }
    return ++dp[node];
}
int find_centroid(int node, int parent, int sz) {
    for (auto i : g[node]) {
        if (i != parent && !seen[i] && dp[i] > sz / 2) {
            return find_centroid(i, node, sz);
        }
    }
    return node;
}
void init_centroid(int node, int parent) {
    int qui = find_centroid(node, 0, get_size(node, 0));
    centree[parent].push_back(qui);
    centree[qui].push_back(parent);
    pater[qui] = parent;
    seen[qui] = true;
    for (auto i : g[qui]) {
        if (!seen[i]) {
            init_centroid(i, qui);
        }
    }
}
void paint(int node, bool flag) {
    function<void(int, int)> dfs = [&](int node, int parent) {
        color[node] = flag;
        for (auto i : centree[node]) {
            if (i != parent) {
                dfs(i, node);
            }
        }
    };
    dfs(node, pater[node]);
}
void dfs(int node, int parent, int d) {
    depth[node] = d;
    pater2[node] = parent;
    rmq[node][0] = parent;
    for (int i = 1; i <= 17; ++i) {
        rmq[node][i] = rmq[rmq[node][i - 1]][i - 1];
    }
    for (auto i : g[node]) {
        if (i != parent) {
            dfs(i, node, d + 1);
        }
    }
}
int anc(int node, int k) {
    for (int i = 17; i >= 0; --i) {
        if (k & (1 << i)) {
            node = rmq[node][i];
            k -= (1 << i);
        }
    }
    return node;
}
int get_depth(int node, int root) {
    return depth[node] - depth[root];
}
void compute_powers() {
    power[0] = 1;
    for (int i = 1; i <= 50000; ++i) {
        power[i] = (1ll * power[i - 1] * p) % mod;
    }
    int invp = invers(p);
    inv[0] = 1;
    for (int i = 1; i <= 50000; ++i) {
        inv[i] = (1ll * inv[i - 1] * invp) % mod;
    }
}
void compute_up(int root) {
    function<void(int, int, int)> dfs = [&](int node, int parent, int hash) {
        if (!color[node]) {
            return;
        }
        up[node] = ((1ll * hash * p) % mod + (s[node] - 'a' + 1)) % mod;
        for (auto i : g[node]) {
            if (i != parent) {
                dfs(i, node, up[node]);
            }
        }
    };
    dfs(root, pater2[root], 0);
}
void compute_down(int root) {
    function<void(int, int, int)> dfs = [&](int node, int parent, int hash) {
        if (!color[node]) {
            return;
        }
        down[node] = hash + power[get_depth(node, root)] * (s[node] - 'a' + 1);
        for (auto i : g[node]) {
            if (i != parent) {
                dfs(i, node, up[node]);
            }
        }
    };
    dfs(root, pater2[root], 0);
}
int hashup(int a, int b, int root) { // b e stramos al lui a !!!!
    if (b == root) {
        return up[a];
    }
    else {
        return (up[a] - (1ll * up[pater2[b]] * power[get_depth(a, root) - get_depth(b, root) + 1]) % mod + mod) % mod;
    }
}
int hashdown(int a, int b, int root) {
    if (b == root) {
        return down[a];
    }
    return (1ll * (down[a] - down[b] + mod) % mod * inv[get_depth(b, root)]) % mod;
}
bool palindrome(int a, int b, int root) {
    return hashup(a, b, root) == hashdown(a, b, root);
}
bool check(int root, int length) {
    paint(root, 1);
    compute_up(root);
    compute_down(root);
    function<void(int, int)> add = [&](int node, int parent) {
        if (!color[node]) {
            return;
        }
        hashes[get_depth(node, root) + 1].insert(up[node]);
        for (auto i : g[node]) {
            if (i != parent) {
                add(i, node);
            }
        }
    };
    function<void(int, int)> rem = [&](int node, int parent) {
        if (!color[node]) {
            return;
        }
        hashes[get_depth(node, root) + 1].erase(hashes[get_depth(node, root) + 1].find(up[node]));
        for (auto i : g[node]) {
            if (i != parent) {
                rem(i, node);
            }
        }
    };
    function<bool(int, int, int)> dfs = [&](int node, int parent, int subtree) {
        if (!color[node]) {
            return false;
        }
        int d = get_depth(node, root);
        int req = length - d;
        bool ans = false;
        if (d >= req) {
            if (req != 0) {
                int qui = anc(d, req);
                int hash = hashup(node, anc(d, req - 1), root);
                if (hashes[req].find(hash) != hashes[req].end() && (d != req || palindrome(qui, subtree, root))) {
                    ans = true;
                }
            }
            for (auto i : g[node]) {
                if (i != parent) {
                    ans |= dfs(i, node, subtree);
                }
            }
        }
        else {
            for (auto i : g[node]) {
                if (i != parent) {
                    ans |= dfs(i, node, subtree);
                }
            }
        }
        return ans;
    };
    function<bool(int, int)> dfs2 = [&](int node, int parent) {
        if (!color[node]) {
            return false;
        }
        int d = get_depth(node, root) + 1;
        bool ok = false;
        if (d == length) {
            ok = palindrome(node, root, root);
        }
        for (auto i : g[node]) {
            if (i != parent) {
                ok |= dfs2(i, node);
            }
        }
        return ok;
    };
    bool ans = false;
    add(root, pater2[root]);
    for (auto i : g[root]) {
        if (i != pater2[root]) {
            rem(i, root);
            ans |= dfs(i, root, i);
            add(i, root);
        }
    }
    ans |= dfs2(root, pater2[root]);
    rem(root, pater2[root]);
    paint(root, 0);
    return ans;
}
bool check_centroids(int length) {
    for (int i = 1; i <= n; ++i) {
        if (check(i, length)) {
            return true;
        }
    }
    return false;
}
int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    cin >> n >> s;
    s = '$' + s; // nu sunt colcalar
    for (int i = 1; i < n; ++i) {
        int x, y;
        cin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    init_centroid(1, 0);
    dfs(1, 1, 0);
    compute_powers();
    int ans = 0;
    for (int i = n; i >= 1; --i) {
        if (check_centroids(i)) {
            ans = i;
            break;
        }
    }
    cout << ans;
}
# 결과 실행 시간 메모리 Grader output
1 Incorrect 180 ms 5496 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Execution timed out 5060 ms 16468 KB Time limit exceeded
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Execution timed out 5071 ms 16316 KB Time limit exceeded
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 180 ms 5496 KB Output isn't correct
2 Halted 0 ms 0 KB -