2018 icpc Regional Dhaka F Path Intersection

F Path Intersection

题意:求Q次树上路径交。

题解:树链剖分之后,对于每一条路径,暴力的往上跳,并且用线段树维护一下个数,最终我们需要线段树中最大值和个数。复杂度O(nlog^2n),码量巨大。

#include<bits/stdc++.h>

using namespace std;

typedef pair<int,int> PII;

#define fi first
#define se second
#define MP make_pair
#define lson (nd<<1)
#define rson (nd<<1|1)

const int N = 100005;

int tag[N<<2], mn[N<<2], mx[N<<2];

int son[N], sz[N], top[N], fa[N], dep[N];

int head[N], to[N<<1], Next[N<<1], tol;

int L[N], id[N], dfn;

int n;

PII st[N*25];

int tot;

void addAdge(int u, int v){
    Next[++tol]=head[u];to[tol]=v;head[u]=tol;
    Next[++tol]=head[v];to[tol]=u;head[v]=tol;
}

void dfs1(int u){
    sz[u]=1;
    for(int e=head[u];e;e=Next[e]){
        int v=to[e];
        if(v==fa[u])continue;
        fa[v]=u;
        dep[v]=dep[u]+1;
        dfs1(v);
        sz[u]+=sz[v];
        if(sz[v]>sz[son[u]])son[u]=v;
    }
}

void dfs2(int u){
    L[u]=++dfn;id[dfn]=u;
    if(son[u])top[son[u]]=top[u],dfs2(son[u]);
    for(int e=head[u];e;e=Next[e]){
        int v=to[e];
        if(v==fa[u]||v==son[u])continue;
        top[v]=v;
        dfs2(v);
    }
}

int LCA(int u, int v){
    while(top[u]!=top[v]){
        if(dep[top[u]]>dep[top[v]]){
            u=fa[top[u]];
        }else{
            v=fa[top[v]];
        }
    }

    if(dep[u]<dep[v])return u;
    else return v;
}

void getSeg(int u, int v){
    while(top[u]!=top[v]){
        st[++tot]=MP(L[top[u]],L[u]);
        u=fa[top[u]];
    }

    st[++tot]=MP(L[v],L[u]);
}

void pushUp(int nd){
    mx[nd]=max(mx[lson],mx[rson]);
    mn[nd]=min(mn[lson],mn[rson]);
}

void pushDown(int nd){
    if(tag[nd]){
        tag[lson]+=tag[nd];
        tag[rson]+=tag[nd];
        mx[lson]+=tag[nd];
        mx[rson]+=tag[nd];
        mn[lson]+=tag[nd];
        mn[rson]+=tag[nd];
        tag[nd]=0;
    }
}

void modify(int nd, int l, int r, int L, int R, int v){
    if(L>r||R<l)return;

    if(L<=l&&r<=R){
        mx[nd]+=v;
        mn[nd]+=v;
        tag[nd]+=v;
        return;
    }

    int mid=l+r>>1;

    pushDown(nd);

    if(L<=mid){
        modify(lson,l,mid,L,R,v);
    }

    if(mid+1<=R){
        modify(rson,mid+1,r,L,R,v);
    }

    pushUp(nd);
}

int query(int nd, int l, int r, int MX){
    if(mx[nd]!=MX){
        return 0;
    }

    if(mx[nd]==mn[nd]){
        return r-l+1;
    }

    int mid=l+r>>1;

    pushDown(nd);

    return query(lson,l,mid,MX)+query(rson,mid+1,r,MX);
}

int main(){
    int T;scanf("%d",&T);

    int kase=1;

    while(T--){
        memset(head, 0, sizeof head);
        memset(son, 0, sizeof son);/*¿Óµã*/
        tol=dfn=0;

        scanf("%d",&n);
        for(int i=1;i<n;++i){
            int u,v;
            scanf("%d%d",&u,&v);
            addAdge(u,v);
        }

        dep[1]=1;
        top[1]=1;

        dfs1(1);

        dfs2(1);


        int q;
        scanf("%d",&q);
        printf("Case %d:\n",kase++);
        for(int iter=1;iter<=q;++iter){
            int K;scanf("%d",&K);
            tot=0;
            vector<int> rt;
            for(int iter1=1;iter1<=K;++iter1){
                int u, v;
                scanf("%d%d",&u,&v);
                int lca=LCA(u,v);

                getSeg(u,lca);
                getSeg(v,lca);
                rt.push_back(L[lca]);
            }

            for(int i=1;i<=tot;++i){
                modify(1,1,n,st[i].fi,st[i].se,1);
            }

            for(auto& nd:rt){
                modify(1,1,n,nd,nd,-1);
            }

            int res=query(1,1,n,K);

            for(int i=1;i<=tot;++i){
                modify(1,1,n,st[i].fi, st[i].se,-1);
            }

            for(auto& nd:rt){
                modify(1,1,n,nd,nd,1);
            }

            printf("%d\n",res);
        }
    }

    return 0;
}

posted @ 2020-10-20 11:03  John_Ran  阅读(109)  评论(0编辑  收藏  举报