Codeforces 1062E 題解
阿新 • • 發佈:2018-11-15
給出一棵有根樹,1為根結點,接下來q次詢問,每次給出一個[l,r]區間,現在允許刪掉[l,r]區間內任何一個點,使得所有點的最近公共祖先的深度儘可能大,問刪掉的點是哪個點,深度最大是多少。
做法:
線段樹維護區間dfs序的最大值,最小值。
首先,區間的LCA等價於區間dfs序的最小值和最大值對應的兩個點的LCA。
然後,根據dfs序的性質,當刪掉的點的dfs序最大或者最小時,對答案貢獻最大。
所以接下來只要去查詢區間裡的LCA(最小值,次大值),以及LCA(次小值,最大值),兩個LCA中深度最大的就是答案。
1 #include<bits/stdc++.h> 2View Codeusing namespace std; 3 const int maxn=1e5+5; 4 #define ll long long 5 int ccnt=0; 6 int n,cnt,f[maxn],d[maxn],siz[maxn],son[maxn],rk[maxn],top[maxn],tid[maxn];//tid:dfs rk:anti-dfs 7 int d_mx; 8 struct edge 9 { 10 int to,next; 11 }e[maxn]; 12 int head[maxn]; 13 inline voidaddedge(int u,int v) 14 { 15 e[++ccnt].to=v; 16 e[ccnt].next=head[u]; 17 head[u]=ccnt; 18 } 19 void dfs1(int u,int fa,int depth) 20 { 21 f[u]=fa; 22 d[u]=depth; 23 d_mx=max(d_mx,d[u]); 24 siz[u]=1; 25 for(int i=head[u]; i ; i=e[i].next) 26 {27 int v=e[i].to; 28 if(v==fa) 29 continue; 30 dfs1(v,u,depth+1); 31 siz[u]+=siz[v]; 32 if(siz[v]>siz[son[u]]) 33 son[u]=v; 34 } 35 } 36 void dfs2(int u,int t) 37 { 38 top[u]=t; 39 tid[u]=++cnt; 40 rk[cnt]=u; 41 if(!son[u]) 42 return; 43 dfs2(son[u],t); 44 for(int i=head[u]; i ; i=e[i].next) 45 { 46 int v=e[i].to; 47 if(v!=son[u]&&v!=f[u]) 48 dfs2(v,v); 49 } 50 } 51 int LCA(int x,int y) 52 { 53 if(x==y) 54 return x; 55 int fx=top[x],fy=top[y]; 56 while(fx!=fy) 57 { 58 if(d[fx]>=d[fy]) 59 { 60 x=f[fx]; 61 } 62 else 63 { 64 y=f[fy]; 65 } 66 fx=top[x]; 67 fy=top[y]; 68 } 69 if(tid[x]<=tid[y]) return x; 70 else return y; 71 } 72 #define lson o*2 73 #define rson o*2+1 74 #define m (l+r)/2 75 struct segment 76 { 77 int mx,mn; 78 }tr[4*maxn]; 79 inline void pushup(int o) 80 { 81 tr[o].mx=max(tr[lson].mx,tr[rson].mx); 82 tr[o].mn=min(tr[lson].mn,tr[rson].mn); 83 } 84 inline int ret(int o,int flag) 85 { 86 if(flag) return tr[o].mx; 87 else return tr[o].mn; 88 } 89 void build(int o,int l,int r) 90 { 91 if(l==r) 92 { 93 tr[o].mx=tr[o].mn=tid[l]; 94 return; 95 } 96 build(lson,l,m); 97 build(rson,m+1,r); 98 pushup(o); 99 } 100 int query(int o,int l,int r,int ql,int qr,int flag)//1 mx 0 mn 101 { 102 if(ql>qr) 103 { 104 if(flag) return 0; 105 else return maxn; 106 } 107 if(ql<=l&&qr>=r) 108 return ret(o,flag); 109 if(qr<=m) 110 return query(lson,l,m,ql,qr,flag); 111 if(ql>m) 112 return query(rson,m+1,r,ql,qr,flag); 113 if(flag) 114 return max(query(lson,l,m,ql,qr,flag),query(rson,m+1,r,ql,qr,flag)); 115 else 116 return min(query(lson,l,m,ql,qr,flag),query(rson,m+1,r,ql,qr,flag)); 117 } 118 int main() 119 { 120 int n,q; 121 scanf("%d%d",&n,&q); 122 for(int i=2;i<=n;i++) 123 { 124 int j; 125 scanf("%d",&j); 126 addedge(j,i); 127 } 128 dfs1(1,0,0); 129 dfs2(1,1); 130 build(1,1,n); 131 while(q--) 132 { 133 int l,r; 134 scanf("%d%d",&l,&r); 135 if(l==r) printf("%d %d\n",l,d_mx); 136 int mx=query(1,1,n,l,r,1); 137 int mn=query(1,1,n,l,r,0); 138 mx=rk[mx]; 139 mn=rk[mn]; 140 int cmx=max(query(1,1,n,l,mx-1,1),query(1,1,n,mx+1,r,1)); 141 int cmn=min(query(1,1,n,l,mn-1,0),query(1,1,n,mn+1,r,0)); 142 cmx=rk[cmx]; 143 cmn=rk[cmn]; 144 int lca1=LCA(mx,cmn); 145 int lca2=LCA(mn,cmx); 146 if(d[lca1]<d[lca2]) 147 printf("%d %d\n",mx,d[lca2]); 148 else 149 printf("%d %d\n",mn,d[lca1]); 150 } 151 }