답안 #668098

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
668098 2022-12-02T18:23:08 Z tibinyte Lampice (COCI19_lampice) C++17
42 / 110
5000 ms 10272 KB
#include <bits/stdc++.h>

using namespace std;

const int mod = 1e9 + 9;
const int base = 29;

int add(int x, int y)
{
    x += y;
    if (x >= mod)
    {
        return x - mod;
    }
    return x;
}

int mult(int x, int y)
{
    return (int64_t)x * y % mod;
}

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
int random(int st, int dr)
{
    uniform_int_distribution<mt19937::result_type> gen(st, dr);
    return gen(rng);
}
struct lampice
{
    int n;
    vector<vector<int>> g;
    vector<char> colors;
    vector<bool> seen;
    vector<int> sz;
    vector<int> depth;
    vector<int> hashup;
    vector<int> hashdown;
    vector<int> par;
    vector<int> nodes;
    vector<int> neortodox;
    vector<int> dp;
    void init(int _n)
    {
        n = _n;
        g = vector<vector<int>>(n + 1);
        colors = vector<char>(n + 1);
        seen = vector<bool>(n + 1);
        dp = neortodox = nodes = sz = depth = hashup = hashdown = par = vector<int>(n + 1);
    }
    void set_color(int pos, char x)
    {
        colors[pos] = x;
    }
    void add_edge(int a, int b)
    {
        g[a].push_back(b);
        g[b].push_back(a);
    }
    void dfs_size(int node, int parent)
    {
        sz[node] = 1;
        for (auto i : g[node])
        {
            if (i != parent && !seen[i])
            {
                dfs_size(i, node);
                sz[node] += sz[i];
            }
        }
    }
    int find_centroid(int node, int parent, int size)
    {
        for (auto i : g[node])
        {
            if (i != parent && !seen[i] && sz[i] > size / 2)
            {
                return find_centroid(i, node, size);
            }
        }
        return node;
    }
    int solve(int node, int k)
    {
        int max_depth = 0;
        function<void(int, int, int)> dfs_init = [&](int node, int parent, int d)
        {
            par[node] = parent;
            depth[node] = d;
            dp[node] = 1;
            max_depth = max(max_depth, d);
            for (auto i : g[node])
            {

                if (i != parent && !seen[i])
                {
                    dfs_init(i, node, d + 1);
                    dp[node] = max(dp[node], dp[i] + 1);
                }
            }
            int mx1 = 0, mx2 = 0;
            for (auto i : g[node])
            {
                if (i != parent && !seen[i])
                {
                    if (dp[i] > mx1)
                    {
                        mx2 = mx1;
                        mx1 = dp[i];
                    }
                    else
                    {
                        if (dp[i] > mx2)
                        {
                            mx2 = dp[i];
                        }
                    }
                }
            }
            neortodox[node] = mx1 + mx2 + 1;
        };
        dfs_init(node, 0, 0);
        if (neortodox[node] < k)
        {
            return 0;
        }
        vector<int> power(max_depth + 1);
        power[0] = 1;
        for (int i = 1; i <= max_depth; ++i)
        {
            power[i] = mult(power[i - 1], base);
        }
        function<void(int, int)> compute_hash = [&](int node, int parent)
        {
            hashup[node] = add(mult(base, hashup[parent]), colors[node] - 'a' + 1);
            hashdown[node] = add(hashdown[parent], mult(power[depth[node]], (colors[node] - 'a' + 1)));
            for (auto i : g[node])
            {
                if (i != parent && !seen[i])
                {
                    compute_hash(i, node);
                }
            }
        };
        compute_hash(node, 0);
        function<int(int, int)> get_hashup = [&](int a, int b)
        {
            int c = par[b];
            return add(hashup[a], mod - mult(hashup[c], power[depth[a] - depth[c]]));
        };
        unordered_multiset<int> exista;
        function<void(int, int, int)> add_subtree = [&](int node, int parent, int root)
        {
            exista.insert(get_hashup(node, root));
            for (auto i : g[node])
            {
                if (i != parent && !seen[i])
                {
                    add_subtree(i, node, root);
                }
            }
        };
        function<void(int, int, int)> remove_subtree = [&](int node, int parent, int root)
        {
            exista.erase(exista.find(get_hashup(node, root)));
            for (auto i : g[node])
            {
                if (i != parent && !seen[i])
                {
                    remove_subtree(i, node, root);
                }
            }
        };
        bool este = false;
        int m = 1;
        nodes[1] = node;
        function<void(int, int, int)> dfs = [&](int node, int parent, int d)
        {
            if (este)
            {
                return;
            }
            nodes[++m] = node;
            int t = 2 * d - k;
            int l = k - d;
            if (l >= 0 && t >= 0)
            {
                if (l == 0)
                {
                    if (hashup[node] == hashdown[node])
                    {
                        este = true;
                    }
                }
                else
                {
                    int qui = nodes[m - l];
                    if (hashup[qui] == hashdown[qui] && exista.count(get_hashup(node, nodes[m - l + 1])))
                    {
                        este = true;
                    }
                }
            }
            for (auto i : g[node])
            {
                if (i != parent && !seen[i])
                {
                    dfs(i, node, d + 1);
                }
            }
            --m;
        };
        for (auto i : g[node])
        {
            if (!seen[i])
            {
                add_subtree(i, node, i);
            }
        }
        for (auto i : g[node])
        {
            if (!seen[i])
            {
                remove_subtree(i, node, i);
                dfs(i, node, 2);
                if (este)
                {
                    break;
                }
                add_subtree(i, node, i);
            }
        }
        return este;
    }
    int decomp(int node, int k)
    {
        dfs_size(node, 0);
        node = find_centroid(node, 0, sz[node]);
        int ans = solve(node, k);
        seen[node] = true;
        for (auto i : g[node])
        {
            if (!seen[i])
            {
                ans = max(ans, decomp(i, k));
            }
        }
        return ans;
    }
    void reinit()
    {
        seen = vector<bool>(n + 1);
    }
};
int32_t main()
{
    cin.tie(nullptr)->sync_with_stdio(false);
    int n;
    cin >> n;
    lampice g;
    g.init(n);
    for (int i = 1; i <= n; ++i)
    {
        char x;
        cin >> x;
        g.set_color(i, x);
    }
    for (int i = 1; i < n; ++i)
    {
        int u, v;
        cin >> u >> v;
        g.add_edge(u, v);
    }
    int ans = 1;
    int st = 1, dr = n / 2;
    while (st <= dr)
    {
        int mid = (st + dr) / 2;
        if (g.decomp(1, 2 * mid))
        {
            ans = max(ans, 2 * mid);
            st = mid + 1;
        }
        else
        {
            dr = mid - 1;
        }
        g.reinit();
    }
    st = max(1, ans / 2), dr = n / 2;
    while (st <= dr)
    {
        int mid = (st + dr) / 2;
        if (g.decomp(1, 2 * mid + 1))
        {
            ans = max(ans, 2 * mid + 1);
            st = mid + 1;
        }
        else
        {
            dr = mid - 1;
        }
        g.reinit();
    }
    cout << ans;
}
# 결과 실행 시간 메모리 Grader output
1 Correct 3 ms 340 KB Output is correct
2 Correct 7 ms 416 KB Output is correct
3 Correct 30 ms 552 KB Output is correct
4 Correct 52 ms 596 KB Output is correct
5 Correct 0 ms 212 KB Output is correct
6 Correct 1 ms 212 KB Output is correct
7 Correct 0 ms 212 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 3656 ms 9348 KB Output is correct
2 Correct 1538 ms 9428 KB Output is correct
3 Correct 696 ms 9664 KB Output is correct
4 Correct 761 ms 10040 KB Output is correct
5 Correct 1324 ms 10272 KB Output is correct
6 Correct 636 ms 10244 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Execution timed out 5019 ms 8368 KB Time limit exceeded
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 3 ms 340 KB Output is correct
2 Correct 7 ms 416 KB Output is correct
3 Correct 30 ms 552 KB Output is correct
4 Correct 52 ms 596 KB Output is correct
5 Correct 0 ms 212 KB Output is correct
6 Correct 1 ms 212 KB Output is correct
7 Correct 0 ms 212 KB Output is correct
8 Correct 3656 ms 9348 KB Output is correct
9 Correct 1538 ms 9428 KB Output is correct
10 Correct 696 ms 9664 KB Output is correct
11 Correct 761 ms 10040 KB Output is correct
12 Correct 1324 ms 10272 KB Output is correct
13 Correct 636 ms 10244 KB Output is correct
14 Execution timed out 5019 ms 8368 KB Time limit exceeded
15 Halted 0 ms 0 KB -