题目大意:
有一棵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; }