codeforces div294 E 求到树上两点距离相同点的数目

本文介绍了一种解决LCA(最近公共祖先)问题的方法——树上倍增法,并给出了具体的C++实现代码。文章详细解释了如何通过递归深度和节点倍增来求解两个节点间的特定路径长度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

很显然的lca树上倍增问题

1.两个点是相同点ans=n

2.两个点深度相同ans=n-size 包含x子树-size 包含y子树

3.两个点深度不同:则ans=深的那个向上走step/2步的size-向上走step/2-1的size

然后用倍增写啦==额我的solve函数好丑

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 int parent[200005][25];
 6 int now=0,next[200005],point[200005],head[200005];
 7 int depth[200005],size[200005];
 8 void add(int x,int y)
 9 {
10   next[++now]=head[x];
11   head[x]=now;
12   point[now]=y;
13 }
14 void dfs(int u,int pre,int deep)
15 {
16   parent[u][0]=pre;
17   depth[u]=deep;
18   size[u]=1;
19   for (int i=head[u];i;i=next[i])
20   {
21     int v=point[i];
22     if (v==pre) continue;
23     dfs(v,u,deep+1);
24     size[u]+=size[v];
25   }
26 }
27 void double_build(int n)
28 {
29   int i,j;
30   for (i=0;i<=20;i++)
31     for (j=1;j<=n;j++)
32       if (parent[j][i]<=0) parent[j][i+1]=0;
33       else parent[j][i+1]=parent[parent[j][i]][i];
34 }
35 int go_up(int u,int deep)
36 {
37   for (int k=0;k<=20;k++)
38     if ((deep>>k)&1) u=parent[u][k];
39   return u;
40 }
41 int solve(int n,int u,int v)
42 {
43   int i,step=0,x=u,y=v,f1,f2,f3,f4,judge=0;
44   if (depth[u]>depth[v]) swap(u,v),swap(x,y);
45   for (i=0;i<=20;i++)
46     if ((depth[v]-depth[u])>>i&1)
47     {
48       judge=1;
49       step-=depth[parent[v][i]]-depth[v];
50       v=parent[v][i];
51     }
52   if (u==v){
53     if (step%2) return 0;
54     f1=go_up(y,step/2);
55     f2=go_up(y,step/2-1);
56     return size[f1]-size[f2];
57   }
58   for (i=20;i>=0;i--)
59     if (parent[u][i]!=parent[v][i])
60     {
61       step-=2*(depth[parent[u][i]]-depth[u]);
62       u=parent[u][i];
63       v=parent[v][i];
64     }
65   step+=2;
66   if (step%2) return 0;
67   if (judge==0)
68   {
69     f2=go_up(y,step/2-1);
70     f3=go_up(x,step/2-1);
71     return n-size[f2]-size[f3];
72   }
73   f1=go_up(y,step/2);
74   f2=go_up(y,step/2-1);
75   return size[f1]-size[f2];
76 }
77 int main()
78 {
79   int n,x,y,i,m;
80   scanf("%d",&n);
81   memset(head,0,sizeof(head));
82   for (i=1;i<n;i++)
83   {
84     scanf("%d%d",&x,&y);
85     add(x,y); add(y,x);
86   }
87   dfs(1,0,0);
88   double_build(n);
89   scanf("%d",&m);
90   while (m--)
91   {
92     scanf("%d%d",&x,&y);
93     if (x==y) printf("%d\n",n);
94     else printf("%d\n",solve(n,x,y));
95   }
96   return 0;
97 }
View Code

题目链接:http://codeforces.com/contest/519/problem/E

转载于:https://www.cnblogs.com/xiao-xin/articles/4307759.html

### Codeforces Div. 2 比赛介绍 Codeforces 是一个在线编程竞赛平台,其中Div. 2比赛面向的是那些评分低于2100分的参赛者[^1]。这类比赛旨在挑战并提升程序员解决问题的能力和技术水平。 ### 参与方式 为了参加Codeforces Div. 2的比赛,参与者首先需要注册账号,并确保个人评级满足参与条件。每次比赛前会有一个虚拟房间分配过程,在此期间选手可以选择加入特定的房间或接受随机安排。比赛通常持续两小时,其间可以尝试解决多个不同难度级别的算法问题。 ### 题目难度 Codeforces Div. 2 的题目按照难度分为几个等级,一般情况下: - **A类题**:相对容易入门级的问题,适合新手练习基础逻辑思维和编码技巧。 - **B类题**:稍微复杂一的任务,可能涉及到更深入的数据结构应用或是简单的动态规划概念。 - **C/D类题**:这些属于中等到较难程度的问题,往往要更高的抽象能力和创造性解法设计能力。 - **E/F及以上类别**:非常具有挑战性的高级别难题,不仅考验全面的知识体系掌握情况还涉及到了尖端的研究成果运用[^2]。 ```python # 示例代码用于展示如何连接到Codeforces API获取即将举行的赛事列表 import requests def get_upcoming_contests(): url = "https://codeforces.com/api/contest.list?gym=false" response = requests.get(url).json() upcoming_contests = [] for contest in response['result']: if 'DIV_2' in contest['name'].upper() and contest['phase'] == 'BEFORE': upcoming_contests.append(contest) return upcoming_contests ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值