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 }    
时间: 2025-01-15 12:04:24

2015北京网络赛 Couple Trees 倍增算法的相关文章

2015北京网络赛A题The Cats&#39; Feeding Spots

题意:给你一百个点,找个以这些点为中心的最小的圆,使得这个圆恰好包含了n个点,而且这个圆的边界上并没有点 解题思路:暴力枚举每个点,求出每个点到其他点的距离,取第n大的点,判断一下. 1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 #include<iostream> 5 #include<memory.h> 6 using namespace std; 7 const i

2015北京网络赛 D-The Celebration of Rabbits 动归+FWT

2015北京网络赛 D-The Celebration of Rabbits 题意: 给定四个正整数n, m, L, R (1≤n,m,L,R≤1000). 设a为一个长度为2n+1的序列. 设f(x)为满足x≤ai≤m+x且ai的异或和为0 的序列a的个数. 求 ∑Rx=Lf(x)mod1000000007 思路:因为对于每一个第一次分配后的a序列对应唯一的x,所以我们就枚举x然后在求序列的个数.

2015北京网络赛 F Couple Trees 暴力倍增

Couple Trees Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://hihocoder.com/problemset/problem/1232 Description "Couple Trees" are two trees, a husband tree and a wife tree. They are named because they look like a couple leaning on each other.

acm 2015北京网络赛 F Couple Trees 主席树+树链剖分

提交 题意:给了两棵树,他们的跟都是1,然后询问,u,v 表 示在第一棵树上在u点往根节点走 , 第二棵树在v点往根节点走,然后求他们能到达的最早的那个共同的点 解: 我们将第一棵树进行书链剖,然后第二棵树采用主席树,他的信息来自他的父亲节点,每个点存他在第一棵树 树链剖分后的位置,这样我们每次查询uv的时候我们只要 我们选取u和top[u]这段区间在主席树v这颗树上找,在这个区间能取到的最大值,一旦存在,这个最大值就我们要的,这个点保存着他到根节点这条路上所有点在第一棵树剖分后的位置 #inc

2015 北京网络赛 E Border Length hihoCoder 1231 树状数组 (2015-11-05 09:30)

#1231 : Border Length 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 Garlic-Counting Chicken is a special species living around the Lake of Peking University. A Garlic-Counting Chicken always flies out from home in the morning, goes to some fixed points looki

Hiho coder 1236 2015 北京网络赛 Score

五维偏序..一开始被吓到了,后来知道了一种BITSET分块的方法,感觉非常不错. 呆马: 1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <cmath> 6 #include <vector> 7 #include <bitset> 8 #define inf 100000000

hihocoder 1236(2015北京网络赛 J题) 分块bitset乱搞题

题目大意: 每个人有五门课成绩,初始给定一部分学生的成绩,然后每次询问给出一个学生的成绩,希望知道在给定的一堆学生的成绩比这个学生每门都低或者相等的人数 因为强行要求在线查询,所以题目要求,每次当前给定的学生成绩都异或上一次的答案 先将学生按每一门成绩都排一次序 这里将学生分块成sqrt(n)的块数,然后在当前块中用bitset容器来记录含有学生的状态 这里可以记录状态的前缀和,因为比后面成绩好的,必然比前面的学生的成绩也好 查询的时候只要查到正好比他高的学生属于哪一块,这样只要访问sqrt(n

2015北京网络赛 G Boxes BFS+打表

G Boxes 题意:n个位置摆有n个箱子,每次移动只能把相邻的垒起来,且上面的必须小于下面的.求摆成升序需要移动多少步. 思路:这里的n很小,只有7.但是bfs最快的情况需要2s左右,所以就打表了. 诡异的是n = 6时居然都跑不出来都超时,连6也打了个表. 1 #include <iostream> 2 #include <cstdio> 3 #include <fstream> 4 #include <algorithm> 5 #include <

2015 北京网络赛 C Protecting Homeless Cats hihoCoder 1229 树状数组

题意:求在平面上 任意两点连线,原点到这个点的距离小于d的点对有多少个,n=200000; 解: 以原点为圆心做一个半径为d的圆,我们知道圆内的点和园内以外的点的连线都是小于d的还有,圆内和园内的点联线也是小于d的,那么需要处理的是圆外和圆外的点. 以每个圆外的点 向圆做切线 然后我们知道有绿色点区域是允许和他搭配的 那么这些点有一个共同特点 那就他们和圆的切线都在 那个点切点的一侧,这样我们就让每个点 转化为两个切点,然后按照极角排序,求出那些不想交区间就是不合法的 #include <ios