zoukankan      html  css  js  c++  java
  • 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;
    }
    
    
  • 相关阅读:
    使用字体图标完整步骤
    用position:absolute定位小窗口位于版面正中心
    MySql 技术内幕 (第7章 游标)
    MySql 技术内幕 (第5章 联接与集合操作)
    赋值语句作为判断的条件
    发布订阅模式和观察者模式
    关系代数
    数据库关系代数表达式学习
    软考通过分数
    哈希表——线性探测法、链地址法、查找成功、查找不成功的平均长度
  • 原文地址:https://www.cnblogs.com/JohnRan/p/13845222.html
Copyright © 2011-2022 走看看