[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 }
时间: 2024-10-30 21:38:25

[CF832D] Misha, Grisha and Underground的相关文章

Codeforces 832D - Misha, Grisha and Underground

832D - Misha, Grisha and Underground 思路:lca,求两个最短路的公共长度.公共长度公式为(d(a,b)+d(b,c)-d(a,c))/2. 代码: #include<bits/stdc++.h> using namespace std; #define ll long long #define ls rt<<1,l,m #define rs rt<<1|1,m+1,r const int INF=0x3f3f3f3f; const

Codeforces 832 D Misha, Grisha and Underground

Misha, Grisha and Underground 题意:Misha 和 Grisha 是2个很喜欢恶作剧的孩子, 每天早上 Misha 会从地铁站 s 通过最短的路到达地铁站 f, 并且在每个地铁站上都写上一句话, 然后Grisha 再从地铁站 t 通过最短的路到达地铁站 f, 并且记录下路途上被Misha写上字的地铁站数目,并且当天晚上会人会将地铁站清理干净,不会干扰第二天的计数, 现在给你3个地铁站 a, b, c, 现在求Misha记录的数目最大能是多少. 代码:求出Lca(a,

Codeforces Round #425 (Div. 2) Problem D Misha, Grisha and Underground (Codeforces 832D) - 树链剖分 - 树状数组

Misha and Grisha are funny boys, so they like to use new underground. The underground has n stations connected with n - 1 routes so that each route connects two stations, and it is possible to reach every station from any other. The boys decided to h

Misha, Grisha and Underground CodeForces - 832D (倍增树上求LCA)

Misha and Grisha are funny boys, so they like to use new underground. The underground has n stations connected with n - 1 routes so that each route connects two stations, and it is possible to reach every station from any other. The boys decided to h

【树链剖分】【dfs序】【LCA】【分类讨论】Codeforces Round #425 (Div. 2) D. Misha, Grisha and Underground

一棵树,q次询问,每次给你三个点a b c,让你把它们选做s f t,问你把s到f +1后,询问f到t的和,然后可能的最大值是多少. 最无脑的想法是链剖线段树--但是会TLE. LCT一样无脑,但是少一个log,可以过. 正解是分类讨论, 如果t不在lca(s,f)的子树内,答案是dis(lca(s,f),f). 如果t在lca(s,f)的子树内,并且dep(lca(s,t))>dep(lca(f,t)),答案是dis(lca(s,t),f): 否则答案是dis(lca(f,t),f). #in

Codeforces Round #425 (Div. 2) D. Misha, Grisha and Underground

题意:给出 一颗树,然后q个询问,每个询问给出3个点,让我们自己选择一个起点一个终点,这条路线上的点标记,问第三个点到终点的最多标记点是多少 思路:第三个点到终点的标记点,肯定是第三个点与起点的最近公共祖先到终点的标记点.我们可以求出三个点的的三种最近公共祖先,取深度最大的点K,然后求K到三个点的距离+1 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1e5+10; 4 5 const int DEG=17; 6

Codeforces Round #425 D

Misha, Grisha and Underground 题意:给一颗树,每个点权值为1,q个询问,每个询问给出a,b,c,3 个点,选择一个点为起点,一个点为终点,形成一条路径,第3个点做为第二条路径的起点,问2条路径上重复区间的点权和的最大值 思路:树链剖分或者LCA,树链剖分映射到数状数组上,没有更新,求出ab ac bc之间的权值和,最长的路径和第二长的路径重复的部分就是答案 AC代码: #include "iostream" #include "string.h&

1月18日 LCA专项训练

A. Lorenzo Von Matterhorn B.Minimum spanning tree for each edge C.Misha, Grisha and Underground D.Fools and Roads E.City Driving 题意:给你一颗基环树(有n条边,n个点的连通图),有Q个询问,求u,v之间的距离最小是多少 思路:对于一棵基环树而言,只要去掉其环上任意一条边(a , b),其边权为w ,剩下的边就可以构成一棵树 对于 u,v 之间的最小距离 , 有可能由去

URAL 1205 By the Underground or by Foot?(SPFA)

By the Underground or by Foot? Time limit: 1.0 secondMemory limit: 64 MB Imagine yourself in a big city. You want to get from point A to point B. To do that you may move by foot or use the underground. Moving by the underground is faster but you may