제출 #1129327

#제출 시각아이디문제언어결과실행 시간메모리
1129327GrayBirthday gift (IZhO18_treearray)C++20
100 / 100
724 ms195108 KiB
#include <algorithm>
#include <bits/stdc++.h>
#include <cassert>
using namespace std;
#define ll long long
#define ull unsigned long long
#define ld long double
#define ff first
#define ss second
#define ln "\n"
#define mp make_pair

const ll INF = 2e18;
const ll MOD = 1e9+7;

struct LCATree{
    vector<vector<ll>> A;
    vector<vector<pair<ll, ll>>> st;
    vector<ll> log, eid, enter, exit;
    vector<pair<ll, ll>> euler;
    ll n, ne;
    LCATree(ll N){
        n=N; A.resize(n+1);
    }
    void add_edge(ll u, ll v){
        A[u].push_back(v);
        A[v].push_back(u);
    }
    void dfs(ll u, ll p, ll &time, ll level){
        euler.push_back({level, u});
        eid[u] = euler.size()-1;
        enter[u]=time++;
        for (auto v:A[u]){
            if (v==p) continue;
            dfs(v, u, time, level+1);
            euler.push_back({level, u});
        }
        exit[u]=time++;
    }
    void init(){
        eid.resize(n+1); enter.resize(n+1); exit.resize(n+1);
        ll time=0;
        dfs(1, 1, time, 1);
        ne = euler.size();
        log.resize(ne+1);
        for (ll i=2; i<=ne; i++) log[i]=log[i/2]+1;
        st.resize(log[ne]+1, vector<pair<ll, ll>>(ne));
        st[0]=euler;
        // cout << "Came" << endl;
        for (ll i=1; i<=log[ne]; i++){
            for (ll j=0; j<ne-(1<<(i-1)); j++){
                st[i][j] = min(st[i-1][j], st[i-1][j+(1<<(i-1))]);
            }
        }
    }
    ll lca(ll l, ll r){
        l=eid[l]; r=eid[r];
        if (l>r) swap(l, r);
        ll len = log[r-l+1];
        return min(st[len][l], st[len][r-(1<<len)+1]).ss;
    }
};

struct SegTree{
    vector<set<pair<ll, ll>>> t;
    ll sz, rsz;
    SegTree(ll N){
        sz=N*4; rsz=N;
        t.resize(sz);
    }

    void build(ll tl, ll tr, ll v, vector<ll> &a){
        if (tl==tr){
            t[v].insert({a[tl], tl});
        }else{
            ll tm = (tl+tr)/2;
            build(tl, tm, v*2, a);
            build(tm+1, tr, v*2+1, a);
            for (auto ch:t[v*2]) t[v].insert(ch);
            for (auto ch:t[v*2+1]) t[v].insert(ch);
        }
    }
    void build(vector<ll> &a){
        build(0, rsz-1, 1, a);
    }
    void update(ll i, ll fx, ll tx, ll tl, ll tr, ll v){
        if (tl==tr){
            assert(i==tl);
            t[v].erase({fx, tl}); t[v].insert({tx, tl});
        }else{
            ll tm = (tl+tr)/2;
            t[v].erase({fx, i}); t[v].insert({tx, i});
            if (i<=tm) update(i, fx, tx, tl, tm, v*2);
            else update(i, fx, tx, tm+1, tr, v*2+1);
        }
    }
    void update(ll i, ll fx, ll tx){
        update(i, fx, tx, 0, rsz-1, 1);
    }
    ll query(ll l, ll r, ll x, ll tl, ll tr, ll v){
        if (l>r) return -1;
        else if (tl==l and tr==r){
            auto it = t[v].lower_bound({x, 0});
            return ((it!=t[v].end() and (*it).ff==x)?(*it).ss:-1);
        }else{
            ll tm = (tl+tr)/2;
            return max(query(l, min(r, tm), x, tl, tm, v*2), query(max(l, tm+1), r, x, tm+1, tr, v*2+1));
        }
    }
    ll query(ll l, ll r, ll x){
        return query(l, r, x, 0, rsz-1, 1);
    }
};

void solve(){
    ll n, m, q; cin >> n >> m >> q;
    LCATree tree(n);
    for (ll i=0; i<n-1; i++){
        ll u, v; cin >> u >> v;
        tree.add_edge(u, v);
    }
    tree.init();
    // return;
    vector<ll> a(m), lca(m);
    for (ll i=0; i<m; i++){
        cin >> a[i];
        if (i) lca[i] = tree.lca(a[i], a[i-1]);
    }
    // SegTree tr(m); tr.build(lca);
    // SegTree self(m); self.build(a);
    // return;
    vector<set<ll>> lind(n+1);
    vector<set<ll>> ind(n+1);
    for (ll i=0; i<m; i++){
        ind[a[i]].insert(i);
        lind[lca[i]].insert(i);
    }
    while (q--){
        ll t; cin >> t;
        if (t==1){
            ll i, v; cin >> i >> v; i--;
            // self.update(i, a[i], v);
            ind[a[i]].erase(i);
            a[i]=v;
            ind[a[i]].insert(i);
            if (i) {
                lind[lca[i]].erase(i);
                lca[i] = tree.lca(a[i], a[i-1]);
                lind[lca[i]].insert(i);
            }
            if (i+1<m) {
                lind[lca[i+1]].erase(i+1);
                lca[i+1] = tree.lca(a[i], a[i+1]);
                lind[lca[i+1]].insert(i+1);
            }
        }else{
            ll l, r, v;
            cin >> l >> r >> v; l--; r--;
            auto i = ind[v].lower_bound(l);
            auto i2 = lind[v].lower_bound(l+1);
            if (i!=ind[v].end() and *i<=r){
                cout << *i+1 << " " << *i+1 << ln;
            }else if (i2!=lind[v].end() and *i2<=r){
                cout << *i2 << " " << *i2+1 << ln;
            }else{
                cout << "-1 -1" << ln;
            }
        }
        // cout << "Done" << endl;
    }
}

int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    auto start = chrono::high_resolution_clock::now();
    ll t=1;
    // cin >> t;
    while (t--) solve();
    #ifdef LOCAL
    auto duration = chrono::duration_cast<chrono::microseconds>(chrono::high_resolution_clock::now() - start);
    cout << setprecision(0) << fixed << "time: " << (double)duration.count()/1000.0 << " milliseconds" << endl;
    #endif
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...