2018 icpc Regional Dhaka G Techland

G techland

题意:给你一颗树,查询连续的一段节点距离某一个节点的最小距离。

题解:考虑树上分块。将连续的节点分成sqrt(n)个块,并且在这些块中,采用树形dp,预处理出距离到每一个节点的最小距离。对于块内的部分O(1)的查询。其他的部分,采用树上dfs序,O(1)查询LCA,暴力搞。(码量稍大)

#include <bits/stdc++.h>

using namespace std;

#define fi first
#define se second
#define MP make_pair

typedef pair<int,int> PII;

const int N = 100005;

const int M = 21;

const int bSize = 300;

const int INF = 0x3f3f3f3f;

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

int n, q, fa[N], dep[N], belong[N], bL[N], bR[N];

PII seg[N];

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;
}

inline void chmin(int& x, int y){
    if(y<x)x=y;
}

struct LCA{
    int L[N<<1], dfn, id[N<<1];

    struct RMQ{
        int stTable[N<<1][M];
        int lg2[N<<1], depth[N<<1];

        void init(int x){
            for(int i=2;i<=x;++i)lg2[i]=lg2[i>>1]+1;
            for(int i=1;i<=x;++i){
                stTable[i][0]=i;
            }

            for(int i=1;i<=20;++i){
                for(int j=1;j+(1<<i)<=x;++j){
                    stTable[j][i]=depth[stTable[j][i-1]]<depth[stTable[j+(1<<i-1)][i-1]]?stTable[j][i-1]:stTable[j+(1<<i-1)][i-1];
                }
            }
        }

        int query(int x, int y){
            if(x>y)swap(x,y);
            int len=lg2[y-x+1];
            return depth[stTable[x][len]]<depth[stTable[y-(1<<len)+1][len]]?stTable[x][len]:stTable[y-(1<<len)+1][len];
        }

    }st;

    void dfs(int u){
        //cout<<"n: "<<n<<" "<<u<<endl;
        L[++dfn]=u;
        id[u]=dfn;
        st.depth[dfn]=dep[u];
        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;
            dfs(v);
            L[++dfn]=u;
            st.depth[dfn]=dep[u];
        }
    }

    void init(){
        dfn=0;
        fa[1]=1;
        dep[1]=0;
        dfs(1);
        st.init(2*n-1);
    }

    inline int query(int u, int v){
        return L[st.query(id[u],id[v])];
    }

    inline int dis(int u, int v){
        return dep[u]+dep[v]-2*dep[query(u,v)];
    }
}qry;

struct bQuery{
    int f[N];

    void init(){
        for(int i=1;i<=n;++i){
            f[i]=INF+INF;
        }
    }

    void dfs(int u){
        for(int e=head[u];e;e=Next[e]){
            int v=to[e];
            if(v==fa[u])continue;
            dfs(v);
            chmin(f[u],f[v]);
        }
    }

    void dfs1(int u){
        f[u]-=2*dep[u];
        chmin(f[u],f[fa[u]]);
        for(int e=head[u];e;e=Next[e]){
            int v=to[e];
            if(v==fa[u])continue;
            dfs1(v);
        }
    }

    void get(int x){
        chmin(f[x],dep[x]);
    }

    void solve(){
        dfs(1);
        dfs1(1);
    }
}bInfo[205];

void clr(){
    memset(head,0,sizeof head);
    tol=0;
    memset(seg,-1,sizeof seg);
}

int bruteForce(int nd, int l, int r){
    int res=INF;
    for(int i=l;i<=r;++i){
        chmin(res,qry.dis(nd,i));
    }
    return res;
}

int getAns(int nd, int p){
    if(seg[p].fi==-1)return INF;

    int res=INF;
    if(belong[seg[p].fi]==belong[seg[p].se]){
        chmin(res,bruteForce(nd,seg[p].fi,seg[p].se));
    }else{
        int l=seg[p].fi, r=seg[p].se;
        chmin(res,bruteForce(nd,l,bR[belong[l]]));
        for(int i=belong[l]+1;i<belong[r];++i){
            chmin(res,bInfo[i].f[nd]+dep[nd]);
        }
        chmin(res,bruteForce(nd,bL[belong[r]],r));
    }

    return res;
}

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

    for(int i=1;i<=100000;++i){
        belong[i]=(i-1)/bSize+1;
        if(i==1||belong[i]!=belong[i-1])bL[belong[i]]=i;
        bR[belong[i]]=i;
    }

    int _;cin>>_;

    int kase=1;

    while(_--){
        clr();

        cin>>n;
        for(int i=1;i<n;++i){
            int u, v;
            cin>>u>>v;
            addAdge(u,v);
        }

        qry.init();

        for(int i=1;i<=belong[n];++i)bInfo[i].init();

        for(int i=1;i<=n;++i){
            bInfo[belong[i]].get(i);
        }

        for(int i=1;i<=belong[n];++i){
            bInfo[i].solve();
        }

        cin>>q;

        int op, l, r, x, m, p;

        cout<<"Case "<<kase++<<":"<<endl;

        while(q--){
            cin>>op;
            if(op==1){
                cin>>x>>l>>r;
                seg[x]=MP(l,r);
            }else if(op==2){
                cin>>x;
                seg[x]=MP(-1,-1);
            }else{
                int res=INF;
                cin>>x>>m;
                for(int i=1;i<=m;++i){
                    cin>>p;
                    chmin(res,getAns(x,p));
                }
                if(res>=INF)res=-1;
                cout<<res<<endl;
            }
        }
    }

    return 0;
}

原文地址:https://www.cnblogs.com/JohnRan/p/13845222.html