Submission #806990

#TimeUsernameProblemLanguageResultExecution timeMemory
806990lukameladzeTourism (JOI23_tourism)C++17
100 / 100
923 ms53484 KiB
# include <bits/stdc++.h>
using namespace std;
#define f first
#define s second
//#define int long long
#define ll long long
#define pii pair <int, int>
#define pb push_back
#define ai3 array <int, 3>
const int N = 3e5 + 5;
int n, m, q,in[N], a[N], out[N], tin, lv[N], par[N][20];
vector <int> v[N];
vector < pii > updates;
void dfs(int a, int p) {
    in[a] = ++tin;
    lv[a] = lv[p] + 1;
    par[a][0] = p;
    for (int i = 1; i <= 18; i++) {
        par[a][i] = par[par[a][i - 1]][i - 1];
    }
    for (int to : v[a]) {
        if (to == p) continue;
        dfs(to, a);
    }
    out[a] = tin;
}
int upper(int a, int b) {
    return (in[a] <= in[b] && out[a] >= out[b]);
}
int lca(int a, int b) {
    if (upper(a, b)) return a;
    for (int i = 18; i >= 0; i--) {
        if (par[a][i] && !upper(par[a][i], b)) a = par[a][i];
    }
    return par[a][0];
}
bool cmp(int a, int b) {
    return in[a] < in[b];
}
int parent[N], added[N],added1[N];
vector <int> g[N];
void dfs1(int a, int p) {
    parent[a] = p;
    for (int to : g[a]) {
        if (to == p) continue;
        dfs1(to, a);
    }
}
int tree[N]; 
void upd(int idx, int val) {
    if (val > 0)
    updates.pb({idx, val});
    for (int i = idx; i < N; i+=i&(-i)) {
        tree[i] += val;
    }
}
int getans(int idx) {
    int pas = 0;
    for (int i = idx; i > 0; i-=i&(-i)) {
        pas += tree[i];
    }
    return pas;
}
vector <ai3> cur_q[N];
int sum[N], ans[N];
void solve(int l, int r, vector <ai3> que) {
    if (l > r || !que.size()) return ;
    vector <ai3> quel, quer;
    int mid = (l + r) / 2;
    
    for (ai3 sth : que) {
        if (sth[0] > mid) quer.pb(sth);
        else if (sth[1] <= mid) quel.pb(sth);
        else cur_q[sth[1]].pb(sth);
    }
    // building virtual tree, (not the most efficient way)
    vector <int> vert, fv;
    for (int i = l; i <= r; i++) {
        vert.pb(a[i]);
    }
    // remove duplicates, sort by in
    sort(vert.begin(), vert.end()); vert.resize(unique(vert.begin(), vert.end()) - vert.begin()); sort(vert.begin(), vert.end(), cmp);
    int sz = (int)vert.size();
    for (int i = 1; i < sz; i++) {
        vert.pb(lca(vert[i - 1], vert[i]));
    }
    sort(vert.begin(), vert.end()); vert.resize(unique(vert.begin(), vert.end()) - vert.begin()); sort(vert.begin(), vert.end(), cmp);
    for (int i = 1; i < (int)vert.size(); i++) { // Virtual tree edges
        int lc = lca(vert[i - 1], vert[i]);  
        g[lc].pb(vert[i]); g[vert[i]].pb(lc);
    }
    dfs1(a[mid], 0);
    for (int x : vert) {
        added[x] = 0; added1[x] = 0;
    }
    sum[mid] = 0;  added[a[mid]] = added1[a[mid]] = mid;
    for (int i = mid - 1; i >= l; i--) {
        int cur = a[i]; int vl = 0;
        //if (l == 4 && r == 6) cout<<"--- "<<i<<"\n";
        while (!added[cur]) {
            added[cur] = i;
          //  if (l == 4 && r == 6) cout<<cur<<" "<<parent[cur]<<" "<<abs(lv[cur] - lv[parent[cur]])<<"\n";
            vl += abs(lv[cur] - lv[parent[cur]]);
            cur = parent[cur];
        }
        sum[i] = sum[i + 1] + vl;
    }
    for (int i = mid + 1; i <= r; i++) {
        int cur = a[i];
        while (!added1[cur]) {
            if (added[cur] != mid) upd(added[cur] + 1, abs(lv[cur] - lv[parent[cur]]));
            added1[cur] = i;
            cur = parent[cur];
        }
        for (ai3 sth : cur_q[i]) {
            ans[sth[2]] = getans(sth[0]) + sum[sth[0]];
        }
        cur_q[i].clear();
    }
    for (pii sth : updates) {
        upd(sth.f, -sth.s);
    }
    updates.clear();
    for (int x : vert) g[x].clear();
    solve(l, mid, quel);
    solve(mid + 1, r, quer);
}
signed main() {
    std::ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    cin>>n>>m>>q;
    for (int i = 1; i <= n - 1; i++) {
        int a, b;
        cin>>a>>b;
        v[a].pb(b);
        v[b].pb(a);
    }
    dfs(1, 0);
    for (int i = 1; i <= m; i++) {
        cin>>a[i];
    }
    vector < ai3 > queries;
    for (int i = 1; i <= q; i++) {
        int l, r;
        cin>>l>>r;
        if (l == r) ans[i] = 0;
        else
        queries.pb({l, r, i});
    }
    solve(1, m, queries);
    for (int i = 1; i <= q; i++) {
        cout<<ans[i] + 1<<"\n";
    }
}
#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...