제출 #1347026

#제출 시각아이디문제언어결과실행 시간메모리
1347026MMihalevTourism (JOI23_tourism)C++20
10 / 100
5092 ms46216 KiB
#include<iostream>
#include<vector>
#include<algorithm>
#include<set>
#include<cmath>
using namespace std;

const int MAX_N=2e5+5;
const int LOG=17;

int n,m,q;
vector<int>g[MAX_N];
int c[MAX_N];
int parent[MAX_N][LOG];

int sp[MAX_N][LOG];
int which[MAX_N][LOG];
int lg[3*MAX_N];
int first[MAX_N];

int depth[MAX_N];
int T=-1;
int in[MAX_N];
int out[MAX_N];
int ver[MAX_N];

int szsp;
void dfs(int u,int par)
{
    in[u]=++T;
    ver[T]=u;

    sp[++szsp][0]=depth[u];
    which[szsp][0]=u;
    first[u]=szsp;

    parent[u][0]=par;
    for(int j=1;j<LOG;j++)
    {
        parent[u][j]=parent[parent[u][j-1]][j-1];
    }

    for(int v:g[u])
    {
        if(v==par)continue;

        depth[v]=depth[u]+1;
        dfs(v,u);

        sp[++szsp][0]=depth[u];
        which[szsp][0]=u;
    }

    out[u]=T;
}

int lca(int u,int v)
{
    int l=first[u],r=first[v];
    if(l>r)swap(l,r);

    int k=lg[r-l+1];

    if(sp[l][k]<sp[r-(1<<k)+1][k])
    {
        return which[l][k];
    }
    return which[r-(1<<k)+1][k];

    /*if(depth[v]<depth[u])swap(u,v);

    for(int j=LOG-1;j>=0;j--)
    {
        if(depth[v]-(1<<j)>=depth[u])
        {
            v=parent[v][j];
        }
    }

    if(u==v)return u;

    for(int j=LOG-1;j>=0;j--)
    {
        if(parent[u][j]!=parent[v][j])
        {
            u=parent[u][j];
            v=parent[v][j];
        }
    }

    return parent[u][0];*/
}

int cntorder[MAX_N];
int cntorderblock[MAX_N];
int cntlcs[MAX_N];
int cntlcsblock[MAX_N];
int sum;
set<int>s;
int sz;

int nxt,prv,lc_old,lc_new;
void add(int u)
{
    cntorder[in[u]]++;
    cntorderblock[in[u]/sz]++;

    if(cntorder[in[u]]>1)return;
    

    auto it=s.upper_bound(in[u]);
    
    if(it!=s.begin() && it!=s.end())
    {
        nxt=ver[*it];it--;
        prv=ver[*it];

        lc_old=lca(nxt,prv);
        cntlcs[in[lc_old]]--;
        cntlcsblock[in[lc_old]/sz]--;
        sum-=depth[nxt]-depth[lc_old];

        lc_new=lca(u,prv);
        cntlcs[in[lc_new]]++;
        cntlcsblock[in[lc_new]/sz]++;
        sum+=depth[u]-depth[lc_new];

        lc_new=lca(nxt,u);
        cntlcs[in[lc_new]]++;
        cntlcsblock[in[lc_new]/sz]++;
        sum+=depth[nxt]-depth[lc_new];
    }
    else if(it!=s.begin())
    {
        it--;
        prv=ver[*it];

        lc_new=lca(u,prv);
        cntlcs[in[lc_new]]++;
        cntlcsblock[in[lc_new]/sz]++;
        sum+=depth[u]-depth[lc_new];
    }
    else if(it!=s.end())
    {
        nxt=ver[*it];

        lc_new=lca(nxt,u);
        cntlcs[in[lc_new]]++;
        cntlcsblock[in[lc_new]/sz]++;
        sum+=depth[nxt]-depth[lc_new];
    }
    
    s.insert(in[u]);
}

void rem(int u)
{
    cntorder[in[u]]--;
    cntorderblock[in[u]/sz]--;

    if(cntorder[in[u]]>0)return;
    s.erase(in[u]);

    auto it=s.upper_bound(in[u]);
    
    if(it!=s.begin() && it!=s.end())
    {
        nxt=ver[*it];it--;
        prv=ver[*it];

        lc_old=lca(nxt,prv);
        cntlcs[in[lc_old]]++;
        cntlcsblock[in[lc_old]/sz]++;
        sum+=depth[nxt]-depth[lc_old];

        lc_new=lca(u,prv);
        cntlcs[in[lc_new]]--;
        cntlcsblock[in[lc_new]/sz]--;
        sum-=depth[u]-depth[lc_new];

        lc_new=lca(nxt,u);
        cntlcs[in[lc_new]]--;
        cntlcsblock[in[lc_new]/sz]--;
        sum-=depth[nxt]-depth[lc_new];
    }
    else if(it!=s.begin())
    {
        it--;
        prv=ver[*it];

        lc_new=lca(u,prv);
        cntlcs[in[lc_new]]--;
        cntlcsblock[in[lc_new]/sz]--;
        sum-=depth[u]-depth[lc_new];
    }
    else if(it!=s.end())
    {
        nxt=ver[*it];

        lc_new=lca(nxt,u);
        cntlcs[in[lc_new]]--;
        cntlcsblock[in[lc_new]/sz]--;
        sum-=depth[nxt]-depth[lc_new];
    }
}

int calc()
{
    int u=-1,lc=-1;

    for(int b=0;b<=(n-1)/sz;b++)
    {
        if(cntorderblock[b]>0)
        {
            for(int i=b*sz;i<min(n,(b+1)*sz);i++)
            {
                if(cntorder[i]>0)
                {
                    u=ver[i];
                    break;
                }
            }
            if(u!=-1)break;
        }
    }

    for(int b=0;b<=(n-1)/sz;b++)
    {
        if(cntlcsblock[b]>0)
        {
            for(int i=b*sz;i<min(n,(b+1)*sz);i++)
            {
                if(cntlcs[i]>0)
                {
                    lc=ver[i];
                    break;
                }
            }
            if(lc!=-1)break;
        }
    }
    
    if(lc==-1 or in[lc]>in[u])lc=u;

    return sum+(depth[u]-depth[lc]+1);
}

vector<pair<pair<int,int>,int>>queries;
int ans[MAX_N];

int main ()
{
    ios_base::sync_with_stdio(0);
    cin.tie(NULL);
    cout.tie(NULL);

    cin>>n>>m>>q;
    sz=(int)(sqrt(n));
    for(int i=1;i<n;i++)
    {
        int u,v;
        cin>>u>>v;
        g[u].push_back(v);
        g[v].push_back(u);
    }

    dfs(1,0);

    for(int i=1;i<=szsp;i++)lg[i]=(int)(log2(i));
    for(int j=1;j<LOG;j++)
    {
        for(int i=1;i+(1<<j)-1<=szsp;i++)
        {
            if(sp[i][j-1]<sp[i+(1<<(j-1))][j-1])
            {
                sp[i][j]=sp[i][j-1];
                which[i][j]=which[i][j-1];
            }
            else
            {
                sp[i][j]=sp[i+(1<<(j-1))][j-1];
                which[i][j]=which[i+(1<<(j-1))][j-1];
            }
        }
    }

    for(int i=1;i<=m;i++)
    {
        cin>>c[i];
    }

    for(int i=1;i<=q;i++)
    {
        int l,r;
        cin>>l>>r;
        queries.push_back({{l,r},i});
    }

    sort(queries.begin(),queries.end(),[](pair<pair<int,int>,int>a,pair<pair<int,int>,int>b)
{
    if(a.first.first/sz==b.first.first/sz)return a.first.second<b.first.second;
    return a.first.first/sz<b.first.first/sz;
});

    int posl=1,posr=0;

    for(auto [pa,id]:queries)
    {
        int l=pa.first,r=pa.second;

        while(posr<r)
        {
            add(c[++posr]);
        }
        while(posl>l)
        {
            add(c[--posl]);
        }
        while(posr>r)
        {
            rem(c[posr--]);
        }
        while(posl<l)
        {
            rem(c[posl++]);
        }
        
        ans[id]=calc();
    }

    for(int i=1;i<=q;i++)
    {
        cout<<ans[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...