zoukankan      html  css  js  c++  java
  • 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:
    ",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
    ",res);
            }
        }
    
        return 0;
    }
    
    
  • 相关阅读:
    echarts 饼图
    vue echarts
    :style :class
    弹框弹出时禁止页面滚动
    2019-2-10 日记
    2019-1-27 日记
    2019-1-26 日记
    2019-1-3 日记
    2019-1-10 日记
    2019-1-2 日记
  • 原文地址:https://www.cnblogs.com/JohnRan/p/13845321.html
Copyright © 2011-2022 走看看