답안 #555568

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
555568 2022-05-01T07:56:38 Z alextodoran Islands (IOI08_islands) C++17
90 / 100
1029 ms 131072 KB
/**
 ____ ____ ____ ____ ____
||a |||t |||o |||d |||o ||
||__|||__|||__|||__|||__||
|/__\|/__\|/__\|/__\|/__\|

**/

#include <bits/stdc++.h>

#define order curr

using namespace std;

typedef long long ll;

const int N_MAX = 1000000;

int N;
int to[N_MAX + 2], len[N_MAX + 2];
vector <int> adj[N_MAX + 2];
int other (int u, int v) {
    return (u == v ? to[u] : u);
}

int par[N_MAX + 2];
int depth[N_MAX + 2];

pair <int, int> backEdge;

int curr[N_MAX + 2];
void dfs (int u) {
    depth[u] = 0;
    while (u != 0) {
        if (curr[u] <= (int) adj[u].size()) {
            int x = (curr[u] < (int) adj[u].size() ? adj[u][curr[u]] : u);
            curr[u]++;
            int v = other(x, u);
            if (depth[v] == -1) {
                par[v] = x;
                depth[v] = depth[u] + 1;
                u = v;
            } else if (depth[v] > depth[u]) {
                backEdge = make_pair(u, x);
            }
        } else {
            u = other(par[u], u);
        }
    }
}

bitset <N_MAX + 2> root;

ll maxAny[N_MAX + 2];
ll maxDown[N_MAX + 2];

queue <int> q;
//int order[N_MAX + 2];
void compute (int s) {
    q.push(s);
    depth[s] = 0;
    int cnt = 0;
    while (q.empty() == false) {
        int u = q.front(); q.pop();
        order[++cnt] = u;
        for (int x : adj[u]) {
            int v = other(x, u);
            if (depth[v] == -1 && root[v] == false) {
                q.push(v);
                depth[v] = depth[u] + 1;
            }
        }
        {
            int v = to[u];
            if (depth[v] == -1 && root[v] == false) {
                q.push(v);
                depth[v] = depth[u] + 1;
            }
        }
    }
    for (int i = cnt; i >= 1; i--) {
        int u = order[i];
        ll maxDown1 = 0, maxDown2 = 0;
        for (int x : adj[u]) {
            int v = other(x, u);
            if (depth[u] < depth[v] && root[v] == false) {
                maxAny[u] = max(maxAny[u], maxAny[v]);
                maxDown[u] = max(maxDown[u], maxDown[v] + len[x]);
                ll here = maxDown[v] + len[x];
                if (here >= maxDown1) {
                    maxDown2 = maxDown1;
                    maxDown1 = here;
                } else if (here > maxDown2) {
                    maxDown2 = here;
                }
            }
        }
        {
            int v = to[u];
            if (depth[u] < depth[v] && root[v] == false) {
                maxAny[u] = max(maxAny[u], maxAny[v]);
                maxDown[u] = max(maxDown[u], maxDown[v] + len[u]);
                ll here = maxDown[v] + len[u];
                if (here >= maxDown1) {
                    maxDown2 = maxDown1;
                    maxDown1 = here;
                } else if (here > maxDown2) {
                    maxDown2 = here;
                }
            }
        }
        maxAny[u] = max(maxAny[u], maxDown1 + maxDown2);
    }
}

int roots[N_MAX + 2];
int group[N_MAX + 2];
int cntRoots;
int cntGroups;

multiset <ll> s;

int main () {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin >> N;
    for (int u = 1; u <= N; u++) {
        cin >> to[u] >> len[u];
        adj[to[u]].push_back(u);
    }

    fill(depth + 1, depth + N + 1, -1);
    for (int u = 1; u <= N; u++) {
        if (depth[u] == -1) {
            dfs(u);
            int v1, x; tie(v1, x) = backEdge;
            int v2 = other(x, v1);
            swap(v1, v2);
            par[v2] = x;
            cntGroups++;
            int v = v1;
            while (v != v2) {
                root[v] = true;
                roots[++cntRoots] = v;
                group[cntRoots] = cntGroups;
                v = other(par[v], v);
            }
            root[v] = true;
            roots[++cntRoots] = v;
            group[cntRoots] = cntGroups;
        }
    }

    fill(depth + 1, depth + N + 1, -1);
    for (int u = 1; u <= N; u++) {
        if (root[u] == true) {
            compute(u);
        }
    }

    ll answer = 0;
    for (int g = 1, i = 1; g <= cntGroups; g++) {
        int j = i;
        while (j < cntRoots && group[j + 1] == g) {
            j++;
        }
        ll totalLen = 0;
        ll maxLen = 0;
        for (int k = i; k <= j; k++) {
            int u = roots[k];
            totalLen += len[par[u]];
            maxLen = max(maxLen, maxAny[u]);
        }

        ll leng = 0;
        for (int k = j; k > i; k--) {
            int u = roots[k];
            leng += len[par[u]];
            s.insert(maxDown[u] + leng);
        }
        ll lazy = 0;

        for (int k = i, u = roots[i]; k <= j; k++) {
            assert(s.empty() == false);
            maxLen = max(maxLen, *s.rbegin() + lazy + maxDown[u]);
            s.insert(maxDown[u] - lazy);
            lazy += len[par[u]];
            u = other(par[u], u);
            assert(s.find((maxDown[u] + totalLen) - lazy) != s.end());
            s.erase(s.find((maxDown[u] + totalLen) - lazy));
        }
        answer += maxLen;
        s.clear();
        i = j + 1;
    }
    cout << answer << "\n";

    return 0;
}
# 결과 실행 시간 메모리 Grader output
1 Correct 13 ms 23892 KB Output is correct
2 Correct 13 ms 23812 KB Output is correct
3 Correct 15 ms 23892 KB Output is correct
4 Correct 13 ms 23836 KB Output is correct
5 Correct 13 ms 23820 KB Output is correct
6 Correct 14 ms 23764 KB Output is correct
7 Correct 13 ms 23892 KB Output is correct
8 Correct 17 ms 23764 KB Output is correct
9 Correct 13 ms 23764 KB Output is correct
10 Correct 13 ms 23764 KB Output is correct
11 Correct 13 ms 23780 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 14 ms 23892 KB Output is correct
2 Correct 13 ms 23944 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 13 ms 24108 KB Output is correct
2 Correct 16 ms 24176 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 24 ms 24788 KB Output is correct
2 Correct 31 ms 26380 KB Output is correct
3 Correct 24 ms 24996 KB Output is correct
4 Correct 16 ms 24404 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 45 ms 27436 KB Output is correct
2 Correct 60 ms 30560 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 88 ms 35460 KB Output is correct
2 Correct 160 ms 42272 KB Output is correct
3 Correct 159 ms 45548 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 176 ms 48072 KB Output is correct
2 Correct 252 ms 60332 KB Output is correct
3 Correct 406 ms 75604 KB Output is correct
4 Correct 422 ms 79872 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 247 ms 59184 KB Output is correct
2 Correct 859 ms 98688 KB Output is correct
3 Correct 291 ms 69580 KB Output is correct
4 Correct 476 ms 94268 KB Output is correct
5 Correct 472 ms 92060 KB Output is correct
6 Correct 1029 ms 76912 KB Output is correct
7 Correct 653 ms 109888 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 298 ms 90344 KB Output is correct
2 Correct 305 ms 90292 KB Output is correct
3 Runtime error 474 ms 131072 KB Execution killed with signal 9
4 Halted 0 ms 0 KB -