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;
    }
    
  • 相关阅读:
    git线上操作
    IDEA快捷方式
    Java 四种线程池
    java 获取当前天之后或之前7天日期
    如何理解AWS 网络,如何创建一个多层安全网络架构
    申请 Let's Encrypt 通配符 HTTPS 证书
    GCE 部署 ELK 7.1可视化分析 nginx
    使用 bash 脚本把 AWS EC2 数据备份到 S3
    使用 bash 脚本把 GCE 的数据备份到 GCS
    nginx 配置 https 并强制跳转(lnmp一键安装包)
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/9337837.html
Copyright © 2011-2022 走看看