Submission #1334763

#TimeUsernameProblemLanguageResultExecution timeMemory
1334763chikien2009Tourism (JOI23_tourism)C++20
100 / 100
266 ms39068 KiB
#include <bits/stdc++.h>

using namespace std;

void setup()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}

struct SEGMENT_TREE
{
    int tree[400000];
    inline void Update(int ind, int l, int r, int x, int v)
    {
        if (r < x || x < l)
        {
            return;
        }
        if (l == r)
        {
            tree[ind] += v;
            return;
        }
        int m = (l + r) >> 1;
        Update(ind << 1, l, m, x, v);
        Update(ind << 1 | 1, m + 1, r, x, v);
        tree[ind] = tree[ind << 1] + tree[ind << 1 | 1];
    }
    inline int Get(int ind, int l, int r, int x, int y)
    {
        if (r < x || y < l)
        {
            return 0;
        }
        if (x <= l && r <= y)
        {
            return tree[ind];
        }
        int m = (l + r) >> 1;
        return Get(ind << 1, l, m, x, y) + Get(ind << 1 | 1, m + 1, r, x, y);
    }
} st;

int n, m, q, a, b;
int c[100000], depth[100000], sz[100000], id[100000], chain[100000], res[100000];
int sp[20][100000], head[20][100000], tail[20][100000];
vector<int> g[100000];
vector<pair<int, int>> query[100000], p[100000];

inline void DFS(int node, int par)
{
    id[node] = a++;
    sz[node] = 1;
    sp[0][node] = par;
    for (int i = 1; i < 20; ++i)
    {
        sp[i][node] = sp[i - 1][sp[i - 1][node]];
    }
    for (auto &i : g[node])
    {
        if (i != par)
        {
            depth[i] = depth[node] + 1;
            DFS(i, node);
            sz[node] += sz[i];
        }
    }
}

inline int GetHead(int l, int r)
{
    int k = __lg(r - l + 1);
    return (id[head[k][l]] < id[head[k][r - (1 << k) + 1]] ? head[k][l] : head[k][r - (1 << k) + 1]);
}

inline int GetTail(int l, int r)
{
    int k = __lg(r - l + 1);
    return (id[tail[k][l]] > id[tail[k][r - (1 << k) + 1]] ? tail[k][l] : tail[k][r - (1 << k) + 1]);
}

inline int LCA(int ina, int inb)
{
    if (depth[ina] < depth[inb])
    {
        swap(ina, inb);
    }
    for (int i = 19; i >= 0; --i)
    {
        if (depth[sp[i][ina]] >= depth[inb])
        {
            ina = sp[i][ina];
        }
    }
    if (ina == inb)
    {
        return ina;
    }
    for (int i = 19; i >= 0; --i)
    {
        if (sp[i][ina] != sp[i][inb])
        {
            ina = sp[i][ina];
            inb = sp[i][inb];
        }
    }
    return sp[0][ina];
}

inline void HLD(int node, int par)
{
    int best = -1;
    for (auto &i : g[node])
    {
        if (i != par && (best == -1 || sz[best] < sz[i]))
        {
            best = i;
        }
    }
    for (auto &i : g[node])
    {
        if (i != par)
        {
            chain[i] = (i == best ? chain[node] : i);
            HLD(i, node);
        }
    }
}

int main()
{
    setup();

    cin >> n >> m >> q;
    for (int i = 0; i < n - 1; ++i)
    {
        cin >> a >> b;
        g[a - 1].push_back(b - 1);
        g[b - 1].push_back(a - 1);
    }
    for (int i = 0; i < m; ++i)
    {
        cin >> c[i];
        c[i]--;
    }
    for (int i = 0; i < q; ++i)
    {
        cin >> a >> b;
        query[b - 1].push_back({a - 1, i});
    }
    a = 0;
    DFS(0, 0);
    HLD(0, 0);
    for (int i = 0; i < m; ++i)
    {
        head[0][i] = tail[0][i] = c[i];
    }
    for (int i = 1; i <= __lg(m); ++i)
    {
        for (int j = 0; j + (1 << i) <= m; ++j)
        {
            head[i][j] = (id[head[i - 1][j]] < id[head[i - 1][j + (1 << (i - 1))]] ? head[i - 1][j] : head[i - 1][j + (1 << (i - 1))]);
            tail[i][j] = (id[tail[i - 1][j]] > id[tail[i - 1][j + (1 << (i - 1))]] ? tail[i - 1][j] : tail[i - 1][j + (1 << (i - 1))]);
        }
    }
    for (int i = 0, j, k, last; i < m; ++i)
    {
        j = c[i];
        do
        {
            k = chain[j];
            last = depth[k];
            while (last <= depth[j] && !p[k].empty())
            {
                if (p[k].back().first <= depth[j])
                {
                    st.Update(1, 0, m - 1, p[k].back().second, -p[k].back().first + last - 1);
                    last = p[k].back().first + 1;
                    p[k].pop_back();
                }
                else
                {
                    st.Update(1, 0, m - 1, p[k].back().second, -depth[j] + last - 1);
                    last = p[k].back().first + 1;
                }
            }
            p[k].push_back({depth[j], i});
            st.Update(1, 0, m - 1, i, depth[j] - depth[k] + 1);
            j = sp[0][k];
        } while (k != 0);
        for (auto & quest : query[i])
        {
            res[quest.second] = st.Get(1, 0, m - 1, quest.first, i) - depth[LCA(GetHead(quest.first, i), GetTail(quest.first, i))];      
        }
    }
    for (int i = 0; i < q; ++i)
    {
        cout << res[i] << "\n";
    }
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...