zoukankan      html  css  js  c++  java
  • [Codeforces 226E]Noble Knight's Path

    题目大意:
    有一棵n个节点的树,m年。初始每个节点都有。每天有如下操作:
    1. 给定c,让c没有(c只可能没有一次)。
    2. 给定s,t,k,y,求从第y+1年到现在(即忽略y+1年之前的操作1),s到t的路径上第k个有的节点(不存在输出-1)。
    解题思路:
    首先树链剖分,然后对每天建主席树。我们把有设为1,没有设为0。
    则操作1就是单点修改,直接改即可。
    操作2,我们把整条路径拆成s到lca和lca到t,两边分开考虑。
    对于s到lca的路径,让s沿着链往上跳,同时进行区间查询。若区间里的点已经大于等于k,则答案一定在这个区间内。
    对于lca到t的路径,相当于要找的是t到lca上第(路径上有的点总数-k+1)个有的点,则和上面的方法一样。
    那么我们假设已经知道了答案所在区间,如何求答案呢?其实相当于在一个01序列里查询某个区间倒数(从下往上dfs序递减)第k个1的位置,我们把[l,r]区间补成[l,n]区间,然后相当于整棵线段树上查询。
    最后一个问题,如何处理在y+1之前没有的点。
    我们发现,从第y棵主席树到当前的主席树,对应节点如果有变化,则一定是在y+1到现在才没有的。所以主席树上做差即可求出没有的点的个数,有的也能求了。
    时间复杂度(O(nlog^2 n))。

    C++ Code:

    #include<bits/stdc++.h>
    const int N=100005;
    int n,fa[N],rt,cnt=0,sz[N],son[N]={0},top[N],dep[N],idx=0,Q,dfn[N],head[N],hq[N],nodes=0,year[N];
    int ret,L,R;
    inline int readint(){
        int c=getchar(),d=0;
        for(;!isdigit(c);c=getchar());
        for(;isdigit(c);c=getchar())
        d=(d<<3)+(d<<1)+(c^'0');
        return d;
    }
    struct edge{
        int to,nxt;
    }e[N<<1];
    struct SegmentTreeNode{
        int v,ls,rs,l,r,sz;
    }d[N<<5];
    void BigMagician(int now){
        sz[now]=1;
        for(int i=head[now];i;i=e[i].nxt)
        if(fa[e[i].to]==now){
            dep[e[i].to]=dep[now]+1;
            BigMagician(e[i].to);
            sz[now]+=sz[e[i].to];
            if(!son[now]||sz[e[i].to]>sz[son[now]])son[now]=e[i].to;
        }
    }
    void dfs(int now){
        dfn[now]=++idx;hq[idx]=now;
        if(son[now])top[son[now]]=top[now],dfs(son[now]);
        for(int i=head[now];i;i=e[i].nxt)
        if(dep[now]<dep[e[i].to]&&e[i].to!=son[now])
        dfs(top[e[i].to]=e[i].to);
    }
    void build(int l,int r,int&o){
        o=++nodes;
        d[o].l=l,d[o].r=r,d[o].sz=r-l+1;
        if(l==r)d[o].v=1;else{
            int mid=l+r>>1;
            build(l,mid,d[o].ls);
            build(mid+1,r,d[o].rs);
            d[o].v=d[d[o].ls].v+d[d[o].rs].v;
        }
    }
    void modify(int o,int&nw,int&p){
        d[nw=++nodes]=d[o];
        --d[nw].v;
        if(d[o].l!=d[o].r){
            int mid=d[o].l+d[o].r>>1;
            if(p<=mid)modify(d[o].ls,d[nw].ls,p);else
            modify(d[o].rs,d[nw].rs,p);
        }
    }
    void query(int&o,int&nw){
        if(L<=d[o].l&&d[o].r<=R)ret+=d[o].v-d[nw].v;else{
            int mid=d[d[o].ls].r;
            if(L<=mid)query(d[o].ls,d[nw].ls);
            if(mid<R)query(d[o].rs,d[nw].rs);
        }
    }
    void query2(int&o,int&nw,int k){
        if(d[o].l==d[o].r)ret=hq[d[o].l];else{
            if(k<=d[d[o].rs].sz-d[d[o].rs].v+d[d[nw].rs].v)query2(d[o].rs,d[nw].rs,k);else
            query2(d[o].ls,d[nw].ls,k-(d[d[o].rs].sz-d[d[o].rs].v+d[d[nw].rs].v));
        }
    }
    inline int theLCA(int x,int y){
        for(;top[x]!=top[y];)
        if(dep[top[x]]>=dep[top[y]])x=fa[top[x]];else
        y=fa[top[y]];
        return(dep[x]<dep[y])?x:y;
    }
    inline int search_to_lca(int u,int v,int&k,int&y,int&nw){
        while(top[u]!=top[v]){
            ret=0;
            L=dfn[top[u]],R=dfn[u];
            query(y,nw);
            ret=R-L+1-ret;
            if(ret>=k){
                ret=0;
                L=dfn[u]+1,R=n;
                if(L<=n)
                query(y,nw);
                ret=R-L+1-ret;
                k+=ret;
                ret=0;
                query2(y,nw,k);
                return ret;
            }
            k-=ret;
            u=fa[top[u]];
        }
        ret=0;
        L=dfn[v],R=dfn[u];
        query(y,nw);
        ret=R-L+1-ret;
        if(ret>=k){
            ret=0;
            L=dfn[u]+1,R=n;
            if(L<=n)
            query(y,nw);
            ret=R-L+1-ret;
            k+=ret;
            ret=0;
            query2(y,nw,k);
            return ret;
        }
        k-=ret;
        return -1;
    }
    inline int search_on_a_list(int u,int v,int&y,int&nw){
        int ans=0;
        while(top[u]!=top[v]){
            ret=0;
            L=dfn[top[u]],R=dfn[u];
            query(y,nw);
            ret=R-L+1-ret;
            ans+=ret;
            u=fa[top[u]];
        }
        ret=0;
        L=dfn[v],R=dfn[u];
        query(y,nw);
        ret=R-L+1-ret;
        return ans+ret;
    }
    inline int search_from_lca(int u,int v,int&k,int&y,int&nw){
        int all=search_on_a_list(u,v,y,nw);
        if(all<k)return -1;
        k=all-k+1;
        while(top[u]!=top[v]){
            ret=0;
            L=dfn[top[u]],R=dfn[u];
            query(y,nw);
            ret=R-L+1-ret;
            if(ret>=k){
                ret=0;
                L=dfn[u]+1,R=n;
                if(L<=n)
                query(y,nw);
                ret=R-L+1-ret;
                k+=ret;
                ret=0;
                query2(y,nw,k);
                return ret;
            }
            k-=ret;
            u=fa[top[u]];
        }
        ret=0;
        L=dfn[v],R=dfn[u];
        query(y,nw);
        ret=R-L+1-ret;
        if(ret>=k){
            ret=0;
            L=dfn[u]+1,R=n;
            if(L<=n)
            query(y,nw);
            ret=R-L+1-ret;
            k+=ret;
            ret=0;
            query2(y,nw,k);
            return ret;
        }
        k-=ret;
        return -1;
    }
    int main(){
    //    freopen("travel.in","r",stdin);
    //    freopen("travel.out","w",stdout);
        memset(head,0,sizeof head);
        n=readint();
        for(int i=1;i<=n;++i){
            fa[i]=readint();
            if(!fa[i])rt=i;else{
                e[++cnt]=(edge){i,head[fa[i]]};
                head[fa[i]]=cnt;
                e[++cnt]=(edge){fa[i],head[i]};
                head[i]=cnt;
            }
        }
        dep[rt]=1;
        top[rt]=rt;
        BigMagician(rt);
        dfs(rt);
        build(1,n,year[0]);
        Q=readint();
        for(int i=1;i<=Q;++i){
            int opt=readint();
            if(opt==1){
                int p=readint();
                modify(year[i-1],year[i],dfn[p]);
            }else{
                year[i]=year[i-1];
                int u=readint(),v=readint(),k=readint(),y=readint();
                ret=0;
                L=R=dfn[u];
                query(year[y],year[i]);
                if(!ret)++k;
                int lca=theLCA(u,v);
                int ans=search_to_lca(u,lca,k,year[y],year[i]);
                if(!~ans){
                    ret=0;
                    L=R=dfn[lca];
                    query(year[y],year[i]);
                    if(!ret)++k;
                    ans=search_from_lca(v,lca,k,year[y],year[i]);
                }
                if(ans==v||ans==u)ans=-1;
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    正则表达式$的一些用法
    基本类型数据转换(int,char,byte)
    IntelliJ Idea 2017 免费激活方法
    jrebel license server 激活方法
    linux 完全关闭tomcat
    spring data jpa自定义bean字段映射
    idea 启动调试模式总提示端口58346被占用问题
    java使用jsch连接linux
    福大软工 · BETA 版冲刺前准备(团队)
    Alpha 事后诸葛亮
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/9337837.html
Copyright © 2011-2022 走看看