2015北京网络赛 Couple Trees 倍增算法

2015北京网络赛 Couple Trees

题意:两棵树,求不同树上两个节点的最近公共祖先

思路:比赛时看过的队伍不是很多,没有仔细想。今天补题才发现有个 倍增算法,自己竟然不知道。

    解法来自 qscqesze ,这个其实之前如果了解过倍增的话还是不是很难,不过这题的数据也不是很给力,极限数据理论上是过不了的。

    其他解法有树链剖分?并不是很清楚。就这样水过了吧。。。

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <fstream>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <deque>
 7 #include <vector>
 8 #include <queue>
 9 #include <string>
10 #include <cstring>
11 #include <map>
12 #include <stack>
13 #include <set>
14 #define LL long long
15 #define eps 1e-8
16 #define INF 0x3f3f3f3f
17 #define MAXN 100005
18 using namespace std;
19 
20 int f1[MAXN][20], f2[MAXN][20];
21 int deep1[MAXN], deep2[MAXN];
22 int step1, step2, ans;
23 void work(int x, int y){
24     step1 = step2 = 1;
25     while (x != y){
26         if (x < y){
27             //x < y means y is not x's ancestor, so let y up
28             for (int i = 15; i >= 0; i--){
29                 if (f2[y][i] > x){
30                     y = f2[y][i];
31                     step2 += 1 << i;
32                     break;
33                 }
34             }
35             y = f2[y][0];
36             step2++;
37         }
38         else{
39             for (int i = 15; i >= 0; i--){
40                 if (f1[x][i] > y){
41                     x = f1[x][i];
42                     step1 += 1 << i;
43                     break;
44                 }
45             }
46             x = f1[x][0];
47             step1++;
48         }
49     }
50     ans = x;
51 }
52 int main()
53 {
54 #ifndef ONLINE_JUDGE
55     freopen("in.txt", "r", stdin);
56     //freopen("out.txt", "w", stdout);
57 #endif // OPEN_FILE
58     int n, m;
59     while (~scanf("%d%d", &n, &m)){
60         int x, y;
61         deep1[1] = deep2[1] = 1;
62         for (int i = 0; i <= 15; i++){
63             f1[1][i] = f2[1][i] = 1;
64         }
65         for (int i = 2; i <= n; i++){
66             scanf("%d", &x);
67             f1[i][0] = x;
68             deep1[i] = deep1[x] + 1;
69             for (int j = 1; j <= 15; j++){
70                 f1[i][j] = f1[f1[i][j - 1]][j - 1];
71             }
72         }
73         for (int i = 2; i <= n; i++){
74             scanf("%d", &x);
75             f2[i][0] = x;
76             deep2[i] = deep2[x] + 1;
77             for (int j = 1; j <= 15; j++){
78                 f2[i][j] = f2[f2[i][j - 1]][j - 1];
79             }
80         }
81         ans = 0;
82         for (int i = 1; i <= m; i++){
83             scanf("%d%d", &x, &y);
84             x = (x + ans) % n + 1;
85             y = (y + ans) % n + 1;
86             work(x, y);
87             printf("%d %d %d\n", ans, step1, step2);
88         }
89     }
90 }    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值