CF1062E Company
线段树,树状数组,dfn序,lca
题意
给定一颗树,有若干个询问,每个询问给出 \(l\) ,\(r\),要求编号在 \([l,r]\) 中的点任意删去一个之后剩余点的 LCA 深度最大,输出删去点的编号和 LCA 的最大深度。
\(1\le n,m\le 10^5\).
题解
显然,对于区间 \([l,r]\),删除的数一定是 \(dfn\) 的最大或最小值。
用st表和线段树简单维护即可。
代码
#include<bits/stdc++.h>
#define ls (p<<1)
#define rs (p<<1|1)
#define mid (l+r>>1)
// #define int long long
using namespace std;
const int Maxn=1e5+10;
int n,q,cnt;
int nxt[Maxn][22];
int dep[Maxn],dfn[Maxn];
int f[4*Maxn];
int mx[Maxn][22],mn[Maxn][22],lg[Maxn];
vector<int>edge[Maxn];
void dfs(int u,int fa=0)
{
dfn[u]=++cnt;
mx[u][0]=mn[u][0]=u;
for(int v:edge[u]) if(v!=fa)
{
dep[v]=dep[u]+1;
dfs(v);
}
}
int query_mx(int l,int r)
{
int k=lg[r-l+1];
return (dfn[mx[l][k]]>dfn[mx[r-(1<<k)+1][k]]?mx[l][k]:mx[r-(1<<k)+1][k]);
}
int query_mn(int l,int r)
{
int k=lg[r-l+1];
return (dfn[mn[l][k]]<dfn[mn[r-(1<<k)+1][k]]?mn[l][k]:mn[r-(1<<k)+1][k]);
}
int lca(int u,int v)
{
if(dep[u]<dep[v]) swap(u,v);
if(!v) return u;
for(int i=20;i>=0;i--) if(dep[nxt[u][i]]>=dep[v]) u=nxt[u][i];
if(u==v) return u;
for(int i=20;i>=0;i--) if(nxt[u][i]!=nxt[v][i]) u=nxt[u][i],v=nxt[v][i];
return nxt[u][0];
}
void push_up(int p) {f[p]=lca(f[ls],f[rs]);}
void change(int p,int l,int r,int tar)
{
if(l==r) return f[p]=tar,void();
if(tar<=mid) change(ls,l,mid,tar);
else change(rs,mid+1,r,tar);
push_up(p);
}
int query(int p,int l,int r,int tl,int tr)
{
if(tr<tl) return 0;
if(tl<=l && tr>=r) return f[p];
if(tr<=mid) return query(ls,l,mid,tl,tr);
if(tl>mid) return query(rs,mid+1,r,tl,tr);
return lca(query(ls,l,mid,tl,tr),query(rs,mid+1,r,tl,tr));
}
signed main()
{
cin>>n>>q; dep[0]=-1e9;
for(int i=2;i<=n;i++)
{
cin>>nxt[i][0];
edge[nxt[i][0]].push_back(i);
}
for(int i=2;i<=n;i++) lg[i]=lg[i>>1]+1;
dfs(1);
for(int j=1;j<=20;j++)
for(int i=1;i<=n;i++)
nxt[i][j]=nxt[nxt[i][j-1]][j-1];
for(int j=1;j<=20;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
{
if(dfn[mx[i][j-1]]>dfn[mx[i+(1<<(j-1))][j-1]]) mx[i][j]=mx[i][j-1];
else mx[i][j]=mx[i+(1<<(j-1))][j-1];
if(dfn[mn[i][j-1]]<dfn[mn[i+(1<<(j-1))][j-1]]) mn[i][j]=mn[i][j-1];
else mn[i][j]=mn[i+(1<<(j-1))][j-1];
}
for(int i=1;i<=n;i++) change(1,1,n,i);
while(q--)
{
int l,r;
cin>>l>>r;
int p_mx=query_mx(l,r),p_mn=query_mn(l,r);
int res_mx=lca(query(1,1,n,l,p_mx-1),query(1,1,n,p_mx+1,r)),res_mn=lca(query(1,1,n,l,p_mn-1),query(1,1,n,p_mn+1,r));
if(dep[res_mx]<dep[res_mn]) cout<<p_mn<<" "<<dep[res_mn]<<endl;
else cout<<p_mx<<" "<<dep[res_mx]<<endl;
}
return 0;
}

浙公网安备 33010602011771号