Submission #1235820

#TimeUsernameProblemLanguageResultExecution timeMemory
1235820bach25089Birthday gift (IZhO18_treearray)C++20
30 / 100
4094 ms15072 KiB
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 200000;
const int MAXM = 200000;
const int MAXLOG = 18;

vector<int> adj[MAXN+1];
int it[MAXN+1], ot[MAXN+1];
int dep[MAXN+1];
int pt[MAXLOG][MAXN+1];
int timer = 0;

void dfs(int u, int p, int d)
{
    it[u] = timer++;
    dep[u] = d;
    pt[0][u] = p;
    for (int v : adj[u])
    {
        if (v == p) continue;
        dfs(v, u, d+1);
    }
    ot[u] = timer-1;
}

bool oksubtree(int u, int v)
{
    return (it[v] <= it[u] && it[u] <= ot[v]);
}

int lca(int u, int v)
{
    if (dep[u] < dep[v]) swap(u, v);
    int d = dep[u] - dep[v];
    for (int k = MAXLOG-1; k>=0; k--)
    {
        if (d >= (1<<k))
        {
            u = pt[k][u];
            d -= (1<<k);
        }
    }
    if (u == v) return u;
    for (int k = MAXLOG-1; k>=0; k--)
    {
        if (pt[k][u] != pt[k][v])
        {
            u = pt[k][u];
            v = pt[k][v];
        }
    }
    return pt[0][u];
}

int getnode(int u, int v)
{
    if (u == v)
    {
        return 0;
    }
    int d = dep[u] - (dep[v] + 1);
    if (d < 0)
    {
        return -1;
    }
    for (int k = MAXLOG-1; k>=0; k--)
    {
        if (d >= (1<<k))
        {
            u = pt[k][u];
            d -= (1<<k);
        }
    }
    return u;
}

int a[MAXM+1];
set<int> p[MAXN+1];

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

    int n, m, q;
    cin >> n >> m >> q;

    for (int i=1; i<=n; i++)
    {
        adj[i].clear();
    }
    for (int i=0; i<n-1; i++)
    {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    timer = 0;
    dfs(1, 0, 0);

    for (int k=1; k<MAXLOG; k++)
    {
        for (int i=1; i<=n; i++)
        {
            int p = pt[k-1][i];
            if (p == 0)
            {
                pt[k][i] = 0;
            }
            else
            {
                pt[k][i] = pt[k-1][p];
            }
        }
    }

    for (int i=1; i<=m; i++)
    {
        cin >> a[i];
        p[a[i]].insert(i);
    }

    for (int i=0; i<q; i++)
    {
        int type;
        cin >> type;
        if (type == 1)
        {
            int pos, vl;
            cin >> pos >> vl;
            int old_val = a[pos];
            p[old_val].erase(pos);
            a[pos] = vl;
            p[vl].insert(pos);
        }
        else
        {
            int ltv, rtv, vn;
            cin >> ltv >> rtv >> vn;

            auto it = p[vn].lower_bound(ltv);
            if (it != p[vn].end() && *it <= rtv)
            {
                int pos = *it;
                cout << pos << " " << pos << "\n";
            }
            else
            {
                if (n <= 2000 && m <= 2000 && q <= 2000)
                {
                    bool fd = false;
                    for (int x = ltv; x <= rtv; x++)
                    {
                        if (!oksubtree(a[x], vn))
                        {
                            continue;
                        }
                        int sl = a[x];
                        for (int y = x; y <= rtv; y++)
                        {
                            if (!oksubtree(a[y], vn))
                            {
                                break;
                            }
                            if (y != x)
                            {
                                sl = lca(sl, a[y]);
                            }
                            if (sl == vn)
                            {
                                cout << x << " " << y << "\n";
                                fd = true;
                                break;
                            }
                        }
                        if (fd) break;
                    }
                    if (!fd)
                    {
                        cout << "-1 -1\n";
                    }
                }
                else
                {
                    int i = ltv;
                    bool fk = false;
                    while (i <= rtv)
                    {
                        if (!oksubtree(a[i], vn))
                        {
                            i++;
                            continue;
                        }
                        int j = i;
                        while (j <= rtv && oksubtree(a[j], vn))
                        {
                            j++;
                        }
                        if (j - 1 >= i + 1)
                        {
                            int branch_i = getnode(a[i], vn);
                            if (branch_i == -1)
                            {
                                i = j;
                                continue;
                            }
                            for (int k = i+1; k < min(j, i+1001); k++)
                            {
                                int branch_k = getnode(a[k], vn);
                                if (branch_k == -1)
                                {
                                    continue;
                                }
                                if (branch_k != branch_i)
                                {
                                    cout << i << " " << k << "\n";
                                    fk = true;
                                    break;
                                }
                            }
                        }
                        if (fk)
                        {
                            break;
                        }
                        i = j;
                    }
                    if (!fk)
                    {
                        cout << "-1 -1\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...