1. 程式人生 > >[Codeforces 226E]Noble Knight's Path

[Codeforces 226E]Noble Knight's Path

arch tchar tree ear ORC == ron char 同時

題目大意:
有一棵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(n\log^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\n",ans);
        }
    }
    return 0;
}

[Codeforces 226E]Noble Knight's Path