답안 #769277

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
769277 2023-06-29T11:21:15 Z danikoynov Cat Exercise (JOI23_ho_t4) C++14
0 / 100
4 ms 7516 KB
#include<bits/stdc++.h>
#define endl '\n'

using namespace std;
typedef long long ll;

void speed()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
}

const int maxn = 2e5 + 10;

int n, a[maxn], used[maxn], pos[maxn];
vector < int > adj[maxn];
ll dp[maxn];
int rec(int val)
{
    if (used[val])
        return dp[val];
    used[val] = 1;
    int left = 0, right = n + 1;
    for (int i = n; i > val; i --)
    {
        if (pos[i] > pos[val])
        {
            right = min(right, pos[i]);
        }
        else
        {
            left = max(left, pos[i]);
        }
    }

    int mx = -1;
    for (int i = pos[val] + 1; i < right; i ++)
    {
        if (a[i] > mx)
        {
            mx = a[i];
            dp[val] = max(dp[val], (ll)(i - pos[val] + rec(a[i])));
        }
    }
    mx = -1;
    for (int i = pos[val] - 1; i > left; i --)
    {
        if (a[i] > mx)
        {
            mx = a[i];
            dp[val] = max(dp[val], (ll)(pos[val] - i + rec(a[i])));
        }
    }
    return dp[val];
}

int dfs(int v, int p, int mx, int dis, int val)
{
    if (mx > val)
        return 0;

    int ans = 0;
    if (a[v] == mx)
        ans = max((ll)ans, dis + dp[v]);

    for (int u : adj[v])
    {
        if (u == p)
            continue;
        ans = max(ans, dfs(u, v, max(mx, a[u]), dis + 1, val));

    }

    return ans;
}

int best[maxn], par[maxn], depth[maxn];
int tin[maxn], tout[maxn], timer, heavy[maxn];
int occ[2 * maxn], sub[maxn];

void trav(int v)
{
    occ[++ timer] = v;
    tin[v] = timer;
    heavy[v] = -1;
    sub[v] = 1;
    for (int u : adj[v])
    {
        if (u == par[v])
            continue;
        depth[u] = depth[v] + 1;
        par[u] = v;
        trav(u);
        sub[v] += sub[u];
        if (heavy[v] == -1 || sub[heavy[u]] > sub[heavy[v]])
            heavy[v] = u;
        occ[++ timer] = v;
    }
    tout[v] = timer;
}

const int maxlog = 20;
int fp[maxlog][2 * maxn], lg[2 * maxn];

void build_sparse_table()
{
    for (int i = 1; i <= timer; i ++)
    {
        lg[i] = lg[i / 2] + 1;
        fp[0][i] = occ[i];
    }

    for (int j = 1; j < lg[timer]; j ++)
        for (int i = 1; i <= timer - (1 << j) + 1; i ++)
        {
            fp[j][i] = fp[j - 1][i + (1 << (j - 1))];
            if (depth[fp[j - 1][i]] < depth[fp[j][i]])
                fp[j][i] = fp[j - 1][i];
        }
}

int lca_query(int v, int u)
{
    int l = tin[v], r = tin[u];
    if (l > r)
        swap(l, r);
    int len = lg[r - l + 1] - 1, lca = fp[len][r - (1 << len) + 1];
    if (depth[fp[len][l]] < depth[lca])
        lca = fp[len][l];
    return lca;
}

int distance(int v, int u)
{
    return depth[v] + depth[u] - 2 * depth[lca_query(v, u)];
}

struct chain
{
    int left, right, head;

    chain()
    {
        left = 0;
        right = 0;
        head = 0;
    }
} chains[maxn];

int chain_count, chain_idx[maxn], chain_pos[maxn];
int order[maxn];
void hld(int v)
{
    chain_idx[v] = chain_count;
    chain_pos[v] = ++ chains[chain_count].right;
    order[chains[chain_count].right] = v;
    if (heavy[v] != -1)
    {
        hld(heavy[v]);
    }
    for (int u : adj[v])
    {
        if (u == par[v] || u == heavy[v])
            continue;
        chain_count ++;
        chains[chain_count].left = chains[chain_count - 1].right + 1;
        chains[chain_count].right = chains[chain_count - 1].right;
        chains[chain_count].head = u;
        hld(u);
    }
}

int tree[4 * maxn], lazy[4 * maxn];

void propagate(int root, int left, int right)
{
    if (lazy[root] == 0)
        return;

    if (left != right)
    {
        tree[root * 2] = lazy[root];
        tree[root * 2 + 1] = lazy[root];
        lazy[root * 2] = lazy[root];
        lazy[root * 2 + 1] = lazy[root];
    }
    lazy[root] = 0;
}

void update(int root, int left, int right, int qleft, int qright, int val)
{
    if (left > qright || right < qleft)
        return;

    if (left >= qleft && right <= qright)
    {
        tree[root] = val;
        lazy[root] = val;
        return;
    }


    propagate(root, left, right);
    int mid = (left + right) / 2;
    update(root * 2, left, mid, qleft, qright, val);
    update(root * 2 + 1, mid + 1, right, qleft, qright, val);
    tree[root] = max(tree[root * 2], tree[root * 2 + 1]);
}

int query(int root, int left, int right, int qleft, int qright)
{
    if (left > qright || right < qleft)
        return 0;
    if (left >= qleft && right <= qright)
        return tree[root];
    propagate(root, left, right);
    int mid = (left + right) / 2;
    return max(query(root * 2, left, mid, qleft, qright),
               query(root * 2 + 1, mid + 1, right, qleft, qright));
}

int lead[maxn], lf_lead[maxn], rf_lead[maxn];

int find_leader(int v)
{
    if (v == lead[v])
        return v;
    return (lead[v] = find_leader(lead[v]));
}

void unite(int v, int u)
{
    v = find_leader(v);
    u = find_leader(u);
    if (v == u)
        return;
    lf_lead[v] = min(lf_lead[v], lf_lead[u]);
    rf_lead[v] = max(rf_lead[v], rf_lead[u]);
    lead[u] = v;
}

int active[maxn];
void solve()
{
    cin >> n;
    for (int i = 1; i <= n; i ++)
    {
        cin >> a[i];
        pos[a[i]] = i;
    }


    bool chain = true;
    for (int i = 1; i < n; i ++)
    {
        int v, u;
        cin >> v >> u;
        if (!(v == i && u == i + 1))
            chain = false;

        adj[v].push_back(u);
        adj[u].push_back(v);
    }




    trav(1);
    build_sparse_table();
    timer = 0;
    chain_count = 1;
    chains[chain_count].left = 1;
    chains[chain_count].right = 0;
    chains[chain_count].head = 1;
    hld(1);
    /**for (int i = 1; i <= chain_count; i ++)
    {
        cout << "chain " << i << endl;
        for (int j = chains[i].left; j <= chains[i].right; j ++)
            cout << order[j] << " ";
        cout << endl;
    }*/

    for (int i = 1; i <= n; i ++)
    {
        lf_lead[i] = rf_lead[i] = lead[i] = i;
    }

    for (int i = 1; i <= n; i ++)
    {

        int v = pos[i];
        active[v] = 1;
        //cout << "step" << endl;
        //cout << v << endl;
        for (int u : adj[v])
        {
            ///cout << u << endl;
            if (u == par[v])
                continue;
            ///cout << "fine" << endl;
            int cur = query(1, 1, n, chain_pos[u], chain_pos[u]);
            ///cout << chain_pos[u] << " : " << chain_pos[u] << endl;
            if (cur != 0)
            {
                ///cout << "check " << cur << endl;
                dp[v] = max(dp[v], dp[pos[cur]] + distance(v, pos[cur]));
            }
        }



        int cur_idx = chain_idx[v], cur_pos = chain_pos[v];
        while(true)
        {
            if (a[order[cur_pos]] > i)
                break;
            int cur_lead = find_leader(cur_pos), lf = chains[cur_idx].left, rf = cur_pos;
            lf = max(lf, lf_lead[cur_lead]);
            int cur_best = query(1, 1, n, lf, rf);
            ///cout << "check " << cur_best << endl;
            if (cur_best != 0)
                dp[v] = max(dp[v], dp[pos[cur_best]] + distance(v, pos[cur_best]));

            if (lf_lead[cur_lead] > chains[cur_idx].left || par[chains[cur_idx].head] == 0)
                break;

            cur_pos = chain_pos[par[chains[cur_idx].head]];
            cur_idx = chain_idx[order[cur_pos]];
        }

        cur_idx = chain_idx[v];
        cur_pos = chain_pos[v];
        if (active[order[chain_pos[v] - 1]])
            unite(order[chain_pos[v] - 1], v);
        if (active[order[chain_pos[v] + 1]])
            unite(order[chain_pos[v] + 1], v);
        while(true)
        {
            if (a[order[cur_pos]] > i)
                break;
            int cur_lead = find_leader(cur_pos), lf = chains[cur_idx].left, rf = cur_pos;
            lf = max(lf, lf_lead[cur_lead]);
            update(1, 1, n, lf, rf, i);
            ///cout << "updated " << lf << " " << rf << endl;
            if (lf_lead[cur_lead] > chains[cur_idx].left || par[chains[cur_idx].head] == 0)
                break;

            cur_pos = chain_pos[par[chains[cur_idx].head]];
            cur_idx = chain_idx[order[cur_pos]];
        }
        //cout << "dp " << v << " " << dp[v] << endl;
    }

    cout << dp[pos[n]] << endl;



}

int main()
{
    speed();
    solve();
    return 0;
}
/**
5
5 3 2 1 4
1 2
2 3
3 4
4 5
*/

Compilation message

Main.cpp: In function 'void solve()':
Main.cpp:254:10: warning: variable 'chain' set but not used [-Wunused-but-set-variable]
  254 |     bool chain = true;
      |          ^~~~~
# 결과 실행 시간 메모리 Grader output
1 Incorrect 4 ms 7516 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 4 ms 7516 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 4 ms 7516 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 4 ms 7516 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 4 ms 7516 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 4 ms 7468 KB Output is correct
2 Incorrect 4 ms 7508 KB Output isn't correct
3 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 4 ms 7516 KB Output isn't correct
2 Halted 0 ms 0 KB -