[CF832D] Misha, Grisha and Underground
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CF832D] Misha, Grisha and Underground相关的知识,希望对你有一定的参考价值。
题意:给一棵树,若指定三点(f,s,t),泽先江f到s的每一个点染色,答案为f到t路径上染色点的个数
现在给定多组询问(a,b,c),从中确定(f,s,t)使答案最大
这题考场上我居然想了出来并且1A了2333(人生第一次独立做出D绝对不是它太水)
首先让a,b,c分别作为f,取最大的答案
问题变为:已知f,s,t的位置,如何统计答案
分三类讨论(图中f为红色点,棕色路径为答案)
lca(f,s)==lca(f,t)
lca(f,t)==lca(s,t)
lca(f,s)==lca(s,t)
然后统计答案时只需用倍增求各种lca就行了
1 #include<stdio.h>
2 struct edge{
3 int to,next;
4 }e[200010];
5 int n,tot,h[100010],dep[100010],fa[100010][21];
6 void add(int a,int b){
7 tot++;
8 e[tot].to=b;
9 e[tot].next=h[a];
10 h[a]=tot;
11 }
12 void dfs(int f,int x){
13 fa[x][0]=f;
14 dep[x]=dep[f]+1;
15 for(int i=h[x];i;i=e[i].next){
16 if(e[i].to!=f)dfs(x,e[i].to);
17 }
18 }
19 void swap(int&a,int&b){
20 a^=b^=a^=b;
21 }
22 int lca(int x,int y){
23 if(dep[x]<dep[y])swap(x,y);
24 int i;
25 for(i=20;i>=0;i--){
26 if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
27 }
28 if(x==y)return x;
29 for(i=20;i>=0;i--){
30 if(fa[x][i]!=fa[y][i]){
31 x=fa[x][i];
32 y=fa[y][i];
33 }
34 }
35 return fa[x][0];
36 }
37 int max(int a,int b){return a>b?a:b;}
38 int calc(int f,int s,int t){
39 int fs,ft,st,fst;
40 fs=lca(f,s);
41 ft=lca(f,t);
42 st=lca(s,t);
43 fst=lca(fs,ft);
44 if(fs==ft)return dep[f]+dep[st]-2*dep[fst]+1;
45 if(fs==st)return dep[f]-dep[ft]+1;
46 return dep[f]-dep[fs]+1;
47 }
48 int main(){
49 int q,i,j,a,b,c;
50 scanf("%d%d",&n,&q);
51 for(i=2;i<=n;i++){
52 scanf("%d",&a);
53 add(a,i);
54 add(i,a);
55 }
56 dep[0]=-1;
57 dfs(0,1);
58 for(j=1;j<21;j++){
59 for(i=1;i<=n;i++)fa[i][j]=fa[fa[i][j-1]][j-1];
60 }
61 while(q--){
62 scanf("%d%d%d",&a,&b,&c);
63 printf("%d\\n",max(max(calc(a,b,c),calc(b,a,c)),calc(c,a,b)));
64 }
65 }
以上是关于[CF832D] Misha, Grisha and Underground的主要内容,如果未能解决你的问题,请参考以下文章
Misha, Grisha and Underground CodeForces - 832D (倍增树上求LCA)
Codeforces Round #425 (Div. 2) Problem D Misha, Grisha and Underground (Codeforces 832D) - 树链剖分 - 树状
Codeforces 832 D Misha, Grisha and Underground
Codeforces Round #425 (Div. 2) D. Misha, Grisha and Underground