codeforces 1062E Company dfs序+線段樹+lca
阿新 • • 發佈:2018-11-22
題意:給你一顆樹,有q次操作,每次操作詢問一個區間 l r,你可以刪除區間內任意一個節點,使得這個區間的lca最大,並輸出刪除的節點和區間lca。(每次操作獨立不影響下一次操作)
思路:我們可以先在樹上走一遍dfs序,每次詢問的區間,決定lca的肯定是dfs序最大和最小的兩個點,因此我們只要通過線段樹找到區間內最小的la和次小的a,最大的rb和次大的b,然後比較lca(la,b)和lca(a,rb)就可以了。
#include<cstdio> #include<algorithm> #include<vector> using namespace std; const int maxn=1e5+10; vector<int>G[maxn]; int anc[maxn][20],dep[maxn],n,cnt=0; int mx[maxn*4],mn[maxn*4],id[maxn],s[maxn]; void dfs(int u,int fa,int deep) { dep[u]=deep; anc[u][0]=fa; s[u]=++cnt; id[cnt]=u; for(int i=0;i<G[u].size();i++) dfs(G[u][i],u,deep+1); } void init() { for(int j=1;j<19;j++) for(int i=1;i<=n;i++) anc[i][j]=anc[anc[i][j-1]][j-1]; } int lca(int p,int q) { if(dep[p]<dep[q])swap(p,q); for(int i=18;i>=0;i--) if(dep[anc[p][i]]>=dep[q]) p=anc[p][i]; if(p==q)return dep[p]-1; for(int i=18;i>=0;i--) if(anc[p][i]!=anc[q][i]) p=anc[p][i],q=anc[q][i]; return dep[anc[p][0]]-1; } int qmax(int o,int l,int r,int ql,int qr) { if(l>=ql&&r<=qr)return mx[o]; int ls=o*2,rs=o*2+1,m=(l+r)/2,res=0; if(ql<=m)res=qmax(ls,l,m,ql,qr); if(qr>m)res=max(res,qmax(rs,m+1,r,ql,qr)); return res; } int qmin(int o,int l,int r,int ql,int qr) { if(l>=ql&&r<=qr)return mn[o]; int ls=o*2,rs=o*2+1,m=(l+r)/2,res=1e8; if(ql<=m)res=qmin(ls,l,m,ql,qr); if(qr>m)res=min(res,qmin(rs,m+1,r,ql,qr)); return res; } void up(int o,int l,int r,int k,int v) { if(l==r) { mx[o]=mn[o]=v; return; } int ls=o*2,rs=o*2+1,m=(l+r)/2; if(k<=m)up(ls,l,m,k,v); else up(rs,m+1,r,k,v); mx[o]=max(mx[ls],mx[rs]); mn[o]=min(mn[ls],mn[rs]); } int main() { int q,x,l,r; scanf("%d%d",&n,&q); for(int i=2;i<=n;i++) { scanf("%d",&x); G[x].push_back(i); } dfs(1,0,1); init(); for(int i=1;i<=n;i++) up(1,1,n,i,s[i]); while(q--) { scanf("%d%d",&l,&r); int la=qmin(1,1,n,l,r); int rb=qmax(1,1,n,l,r); up(1,1,n,id[la],1e8); int a=qmin(1,1,n,l,r); up(1,1,n,id[la],la); up(1,1,n,id[rb],0); int b=qmax(1,1,n,l,r); up(1,1,n,id[rb],rb); int t1=lca(id[la],id[b]),t2=lca(id[a],id[rb]); if(t1>=t2) printf("%d %d\n",id[rb],t1); else printf("%d %d\n",id[la],t2); } }