• SPOJ 2939. Query on a tree V


    SPOJ 2939. Query on a tree V

    Problem code: QTREE5

     

     

    You are given a tree (an acyclic undirected connected graph) with N nodes. The tree nodes are numbered from 1 to N. We define dist(a, b) as the number of edges on the path from node a to node b.

    Each node has a color, white or black. All the nodes are black initially.

    We will ask you to perfrom some instructions of the following form:

    • 0 i : change the color of i-th node(from black to white, or from white to black).
    • v : ask for the minimum dist(u, v), node u must be white(u can be equal to v). Obviously, as long as node vis white, the result will alway be 0.

    Input

    • In the first line there is an integer N (N <= 100000)
    • In the next N-1 lines, the i-th line describes the i-th edge: a line with two integers a b denotes an edge between a and b.
    • In the next line, there is an integer Q denotes the number of instructions (Q <= 100000)
    • In the next Q lines, each line contains an instruction "0 i" or "1 v"

    Output

    For each "1 v" operation, print one integer representing its result. If there is no white node in the tree, you should write "-1".

    Example

    Input:
    10
    1 2
    1 3
    2 4
    1 5
    1 6
    4 7
    7 8
    5 9
    1 10
    10
    0 6
    0 6
    0 6
    1 3
    0 1
    0 1
    1 3
    1 10
    1 4
    1 6
    
    Output:
    2
    2
    2
    3
    0
    --------------------------------------------------
    题目大意:一颗树,边上权值都是1,一开始树上的节点都是黑色。有两种操作:0操作是将某个节点黑色变白色,白色变黑色;1操作是询问某个节点距离最近的白色节点的距离
    解题思路:跟QTREE4很像,使用树链剖分+堆维护,有了QTREE4的基础,这题就迎刃而解了。自此,QTREE系列就做完了。
    #include <stdio.h>
    #include <string.h>
    #include <vector>
    #include <queue>
    #define clr(a,b) memset(a,b,sizeof(a))
    using namespace std;
    
    const int N=100005,M=N*7,inf=0x7fffffff;
    struct Node{
        int v,p;
        bool operator<(const Node & a)const{
            return v>a.v;
        }
        Node(int a,int c):v(a),p(c){}
    };
    int n,cnum,pnum;
    vector<int>gra[N];
    int son[N],fa[N],top[N],siz[N],white[N];
    int cp[N],cd[N],csz[N],pn[N],cid[M];
    int maxl[M],maxr[M],le[M],ri[M];
    priority_queue<Node>que[N];
    
    void dfs_1(int s,int f){
        fa[s]=f;top[s]=s;siz[s]=1;
        int maxx=0,p=-1,len=gra[s].size();
        for(int i=0;i<len;i++){
            int e=gra[s][i];if(e==f)continue;
            dfs_1(e,s);siz[s]+=siz[e];
            if(siz[e]>maxx){maxx=siz[e];p=e;}
        }son[s]=p;
    }
    
    void build(int p,int rt,int l,int r){
        int root=rt+p;
        le[root]=l;ri[root]=r;
        maxl[root]=maxr[root]=-1;
        int mid=(l+r)>>1;
        if(l==r)return ;
        build(p,rt<<1,l,mid);
        build(p,rt<<1|1,mid+1,r);
    }
    
    void update(int p,int rt,int x){
        int root=rt+p,lroot=p+(rt<<1),rroot=p+(rt<<1|1);
        int l=le[root],r=ri[root],mid=(l+r)>>1;
        if(l==x&&r==x){
            int s=cid[p+x],minn=-1;
            while(!que[s].empty()){
                int v=que[s].top().v;
                int pp=que[s].top().p;
                if(maxl[pp]+1!=v){que[s].pop();continue;}
                minn=v;break;
            }
            if(white[s])maxl[root]=maxr[root]=0;
            else maxl[root]=maxr[root]=minn;
            if(rt==1&&~maxl[root]){
                int f=fa[s];
                if(~f)que[f].push(Node(maxl[root]+1,root));
            }
            return ;
        }
        if(x<=mid)update(p,rt<<1,x);
        else update(p,rt<<1|1,x);
        maxl[root]=maxr[root]=-1;
        if(~maxl[lroot]&&(maxl[root]==-1||maxl[root]>maxl[lroot]))maxl[root]=maxl[lroot];
        if(~maxl[rroot]&&(maxl[root]==-1||maxl[root]>maxl[rroot]+mid-l+1))maxl[root]=maxl[rroot]+mid-l+1;
        if(~maxr[rroot]&&(maxr[root]==-1||maxr[root]>maxr[rroot]))maxr[root]=maxr[rroot];
        if(~maxr[lroot]&&(maxr[root]==-1||maxr[root]>maxr[lroot]+r-mid))maxr[root]=maxr[lroot]+r-mid;
        int s=cid[p+1];
        if(rt==1&&~maxl[root]){
            int f=fa[s];
            if(~f)que[f].push(Node(maxl[root]+1,root));
        }
    }
    
    int queryl(int p,int rt,int l,int r){
        int root=p+rt;
        int mid=(le[root]+ri[root])>>1;
        if(l==le[root]&&r==ri[root])
            return maxl[root];
        if(r<=mid)return queryl(p,rt<<1,l,r);
        else if(l>mid)return queryl(p,rt<<1|1,l,r);
        else{
            int ans=-1;
            int ret=queryl(p,rt<<1,l,mid);
            if(~ret&&(ans==-1||ans>ret))ans=ret;
            ret=queryl(p,rt<<1|1,mid+1,r);
            if(~ret&&(ans==-1||ans>ret+mid-l+1))ans=ret+mid-l+1;
            return ans;
        }
    }
    
    int queryr(int p,int rt,int l,int r){
        int root=p+rt;
        int mid=(le[root]+ri[root])>>1;
        if(l==le[root]&&r==ri[root])
            return maxr[root];
        if(r<=mid)return queryr(p,rt<<1,l,r);
        else if(l>mid)return queryr(p,rt<<1|1,l,r);
        else{
            int ans=-1;
            int ret=queryr(p,rt<<1,l,mid);
            if(~ret&&(ans==-1||ans>ret+r-mid))ans=ret+r-mid;
            ret=queryr(p,rt<<1|1,mid+1,r);
            if(~ret&&(ans==-1||ans>ret))ans=ret;
            return ans;
        }
    }
    
    void dfs_2(int s,int d){
        if(s==top[s]){
            cp[s]=++cnum;csz[cnum]=0;pn[cnum]=pnum;
        }
        while(!que[s].empty())que[s].pop();
        cp[s]=cp[top[s]];cd[s]=d;int k=cp[s];
        csz[k]=d;cid[d+pn[k]]=s;
        if(~son[s]){
            top[son[s]]=top[s];dfs_2(son[s],d+1);
        }
        int len=gra[s].size();
        for(int i=0;i<len;i++){
            int e=gra[s][i];
            if(e!=fa[s]&&e!=son[s])dfs_2(e,1);
        }
        if(son[s]==-1){
            pnum+=6*d;build(pn[k],1,1,d);
        }
    }
    
    int main(){
    //    freopen("/home/axorb/in","r",stdin);
    //    freopen("/home/axorb/out","w",stdout);
        scanf("%d",&n);clr(white,0);
        for(int i=1;i<=n;i++)gra[i].clear();
        for(int i=1;i<n;i++){
            int a,b;scanf("%d%d",&a,&b);
            gra[a].push_back(b);gra[b].push_back(a);
        }
        cnum=pnum=0;dfs_1(1,-1);dfs_2(1,1);
        int q;scanf("%d",&q);
        while(q--){
            int a,b;scanf("%d%d",&a,&b);
            if(a==0){
                white[b]^=1;
                while(~b){
                    update(pn[cp[b]],1,cd[b]);
                    b=fa[top[b]];
                }
            }
            else{
                int minn=-1,tmp=0;
                while(~b){
                    int ll=queryl(pn[cp[b]],1,cd[b],csz[cp[b]]);
                    int rr=queryr(pn[cp[b]],1,1,cd[b]);
                    if(ll!=-1&&(minn==-1||minn>ll+tmp))minn=ll+tmp;
                    if(rr!=-1&&(minn==-1||minn>rr+tmp))minn=rr+tmp;
                    tmp+=cd[b];b=fa[top[b]];
                }
                printf("%d\n",minn);
            }
        }
    }
    

      

    也许有挫折,但这些,怎能挡住湘北前进的步伐
  • 相关阅读:
    Hibernate框架—简介
    ooad单例模式-Singleton
    About-JavaOOAD
    win10内置ubuntu,mysql完美清理,并安装
    VUE关于对象动态添加属性无法双向绑定问题
    正则留档
    centos下tomcat中文路径不识别
    web服务器解释html-include
    rose
    聊天框突出箭头
  • 原文地址:https://www.cnblogs.com/Fatedayt/p/2585671.html
Copyright © 2020-2023  润新知