제출 #1071515

#제출 시각아이디문제언어결과실행 시간메모리
1071515isaachewTourism (JOI23_tourism)C++17
100 / 100
819 ms26824 KiB
#include <bits/stdc++.h>


/*
 HLD + Segtree + Segtree
 */
struct segtree2{//range sum segtree
    int size;
    std::vector<int> nodes;
    segtree2(){}
    void init(int n){
        size=n;
        nodes.resize(2*n-1);
    }
    void update(int p,int x,int nl,int nr,int ni){
        if(p<nl||p>=nr)return;
        if(nl+1>=nr){
            nodes[ni]+=x;
            return;
        }
        int nm=(nl+nr)/2;
        update(p,x,nl,nm,ni+1);
        update(p,x,nm,nr,ni+2*(nm-nl));
        nodes[ni]=nodes[ni+1]+nodes[ni+2*(nm-nl)];
    }
    int query(int l,int r,int nl,int nr,int ni){
        if(l<=nl&&r>=nr){
            return nodes[ni];
        }
        if(r<=nl||l>=nr)return 0;
        int nm=(nl+nr)/2;
        return query(l,r,nl,nm,ni+1)+query(l,r,nm,nr,ni+2*(nm-nl));
    }
};
segtree2 sumseg;
struct segtree{//segtree to keep track of values in the other segtree
    int size;
    std::vector<int> nodes;
    segtree(){}
    void init(int n){
        size=n;
        nodes.resize(2*n-1,-1);
    }
    void update(int l,int r,int x,int nl,int nr,int ni){//
        if(r<=nl||l>=nr)return;
        if(l<=nl&&r>=nr){
            if(nodes[ni]==-2){//recurse on a mix
                int nm=(nl+nr)/2;//reset everything below node
                update(l,r,-1,nl,nm,ni+1);
                update(l,r,-1,nm,nr,ni+2*(nm-nl));
            }else if(nodes[ni]>=0){
                //std::cout<<"["<<nl<<","<<nr<<") not at "<<nodes[ni]<<'\n';
                sumseg.update(nodes[ni],-(nr-nl),0,sumseg.size,0);
            }
            nodes[ni]=x;
            //std::cout<<"["<<nl<<","<<nr<<") at "<<nodes[ni]<<'\n';
            if(nodes[ni]!=-1)sumseg.update(nodes[ni],(nr-nl),0,sumseg.size,0);
            return;
        }
        int nm=(nl+nr)/2;
        if(nodes[ni]>=0){//pushdown
            nodes[ni+1]=nodes[ni];
            nodes[ni+2*(nm-nl)]=nodes[ni];
            nodes[ni]=-2;
        }
        update(l,r,x,nl,nm,ni+1);
        update(l,r,x,nm,nr,ni+2*(nm-nl));
        nodes[ni]=(nodes[ni+1]!=-1||nodes[ni+2*(nm-nl)]!=-1)?-2:-1;
    }
};
segtree mainseg;
int nids=0;
std::vector<int> parents;
std::vector<std::vector<int>> edges;//children
std::vector<int> depths;
std::vector<int> ssizes;
std::vector<int> ids;
std::vector<int> heavys;
std::vector<int> heavybs;
int dfs(int cur,int par){
    parents[cur]=par;
    for(int i:edges[cur]){
        if(i==par)continue;
        depths[i]=depths[cur]+1;
        ssizes[cur]+=dfs(i,cur);
        if(heavys[cur]==-1||ssizes[i]>ssizes[heavys[cur]])heavys[cur]=i;//replace heavy if necessary
    }
    return ssizes[cur];
}
void dfs2(int cur,int heavy){
    ids[cur]=nids++;
    heavybs[cur]=heavy;
    if(heavys[cur]!=-1)dfs2(heavys[cur],heavy);
    for(int i:edges[cur]){
        if(i==heavys[cur]||i==parents[cur])continue;
        dfs2(i,i);
    }
}
int main(){
    std::ios::sync_with_stdio(0);
    std::cin.tie(0);
    int n,m,q;
    std::cin>>n>>m>>q;
    parents.resize(n);
    edges.resize(n);
    ids.resize(n);
    depths.resize(n);
    heavys.resize(n,-1);
    heavybs.resize(n);
    ssizes.resize(n,1);
    std::vector<int> spots;
    for(int i=0;i<n-1;i++){
        int a,b;
        std::cin>>a>>b;
        a--,b--;
        edges[a].push_back(b);
        edges[b].push_back(a);
    }
    for(int i=0;i<m;i++){
        int x;
        std::cin>>x;
        x--;
        spots.push_back(x);
    }
    std::vector<std::pair<int,int>> queries;
    std::vector<int> results(q);
    std::vector<std::vector<int>> squeries(m);//indices per ending time
    for(int i=0;i<q;i++){
        int a,b;
        std::cin>>a>>b;
        a--,b--;
        queries.push_back({a,b});
        squeries[b].push_back(i);
    }
    dfs(0,0);
    dfs2(0,0);
    sumseg.init(m);
    mainseg.init(n);
    for(int i=0;i<m-1;i++){//go
        int src=spots[i],dst=spots[i+1];
        while(heavybs[src]!=heavybs[dst]){
            if(depths[heavybs[src]]>depths[heavybs[dst]]){
                mainseg.update(ids[heavybs[src]],ids[src]+1,i,0,n,0);
                src=parents[heavybs[src]];
            }else{
                mainseg.update(ids[heavybs[dst]],ids[dst]+1,i,0,n,0);
                dst=parents[heavybs[dst]];
            }
        }
        mainseg.update(std::min(ids[src],ids[dst]),std::max(ids[src],ids[dst])+1,i,0,n,0);
        for(int j:squeries[i+1]){
            results[j]=std::max(1,sumseg.query(queries[j].first,queries[j].second,0,m,0));//make sure at least 1 so paths like 3 3 3 visit city 3
        }
    }
    for(int j:squeries[0]){//random edge case: query ends in 1 -> only 1 city visited
        results[j]=1;
    }
    for(int i:results)std::cout<<i<<'\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...