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 }