[Codeforces 226E]Noble Knight's Path
阿新 • • 發佈:2018-07-19
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