Codeforces Round #362 (Div. 2) C. Lorenzo Von Matterhorn (类似LCA)

题目链接:http://codeforces.com/problemset/problem/697/D

给你一个有规则的二叉树,大概有1e18个点。

有两种操作:1操作是将u到v上的路径加上w,2操作是求u到v上的路径和。

我们可以看出任意一个点到1节点的边个数不会超过64(差不多就是log2(1e18)),所以可以找最近相同祖节点的方式写。

用一条边的一个唯一的端点作为边的编号(比如1到2,那2就为这条边的编号),由于数很大,所以用map来存。

进行1操作的时候就是暴力加w至u到LCA(u,v)上的各个边,同样加w至v到LCA(u , v)上的各个边。同理,进行2操作的时候也是暴力求和。

下面这是简单的写法

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef __int64 LL;
 4 map <LL , LL> cnt;
 5 
 6 int main()
 7 {
 8     int n;
 9     LL choose , u , v , val;
10     scanf("%d" , &n);
11     while(n--) {
12         scanf("%lld" , &choose);
13         if(choose == 1) {
14             scanf("%lld %lld %lld" , &u , &v , &val);
15             while(u != v) {
16                 if(u > v) {
17                     cnt[u] += val;
18                     u /= 2;
19                 }
20                 else {
21                     cnt[v] += val;
22                     v /= 2;
23                 }
24             }
25         }
26         else {
27             scanf("%lld %lld" , &u , &v);
28             LL res = 0;
29             while(u != v) {
30                 if(u > v) {
31                     res += cnt[u];
32                     u /= 2;
33                 }
34                 else {
35                     res += cnt[v];
36                     v /= 2;
37                 }
38             }
39             printf("%lld
" , res);
40         }
41     }
42     return 0;
43 }

下面是我一开始的写法,也A了,不过有点麻烦,可以不看。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef __int64 LL;
 4 const int N = 1e3 + 5;
 5 vector <int> vc;
 6 vector <LL> q1[N] , q2[N] , ans1 , ans2;
 7 LL x[N] , y[N] , val[N];
 8 int main()
 9 {
10     int n;
11     LL choose , u , v;
12     scanf("%d" , &n);
13     for(int i = 1 ; i <= n ; ++i) {
14         scanf("%lld" , &choose);
15         if(choose == 1) {
16             scanf("%lld %lld %lld" , x + i , y + i , val + i);
17             vc.push_back(i);
18             LL num1 = x[i] , num2 = y[i];
19             q1[i].push_back(num1) , q2[i].push_back(num2);
20             while(num1 != num2) {
21                 if(num1 > num2) {
22                     num1 /= 2;
23                     q1[i].push_back(num1);
24                 }
25                 else {
26                     num2 /= 2;
27                     q2[i].push_back(num2);
28                 }
29             }
30         }
31         else {
32             scanf("%lld %lld" , &u , &v);
33             LL temp1 = u , temp2 = v , res = 0;
34             ans1.clear() , ans2.clear();
35             ans1.push_back(temp1) , ans2.push_back(temp2);
36             while(temp1 != temp2) {
37                 if(temp1 > temp2) {
38                     temp1 /= 2;
39                     ans1.push_back(temp1);
40                 }
41                 else {
42                     temp2 /= 2;
43                     ans2.push_back(temp2);
44                 }
45             }
46             for(int j = 0 ; j < vc.size() ; ++j) {
47                 int l = 0 , r = ans1.size() - 1 , k = 0;
48                 while(l + 1 <= r) {
49                     for( ; k + 1 < q1[vc[j]].size() ; ++k) {
50                         if(ans1[l] > q1[vc[j]][k])
51                             break;
52                         if(ans1[l + 1] == q1[vc[j]][k + 1] && ans1[l] == q1[vc[j]][k]) {
53                             res += val[vc[j]];
54                         }
55                     }
56                     l++;
57                 }
58                 k = 0 , l = 0 , r = ans1.size() - 1;
59                 while(l + 1 <= r) {
60                     for( ; k + 1 < q2[vc[j]].size() ; ++k) {
61                         if(ans1[l] > q2[vc[j]][k])
62                             break;
63                         if(ans1[l + 1] == q2[vc[j]][k + 1] && ans1[l] == q2[vc[j]][k]) {
64                             res += val[vc[j]];
65                         }
66                     }
67                     l++;
68                 }
69                 
70                 l = 0 , r = ans2.size() - 1 , k = 0;
71                 while(l + 1 <= r) {
72                     for( ; k + 1 < q1[vc[j]].size() ; ++k) {
73                         if(ans2[l] > q1[vc[j]][k])
74                             break;
75                         if(ans2[l + 1] == q1[vc[j]][k + 1] && ans2[l] == q1[vc[j]][k]) {
76                             res += val[vc[j]];
77                         }
78                     }
79                     l++;
80                 }
81                 k = 0 , l = 0 , r = ans2.size() - 1;
82                 while(l + 1 <= r) {
83                     for( ; k + 1 < q2[vc[j]].size() ; ++k) {
84                         if(ans2[l] > q2[vc[j]][k])
85                             break;
86                         if(ans2[l + 1] == q2[vc[j]][k + 1] && ans2[l] == q2[vc[j]][k]) {
87                             res += val[vc[j]];
88                         }
89                     }
90                     l++;
91                 }
92             }            
93             printf("%lld
" , res);
94         }
95     }
96     return 0;
97 }
原文地址:https://www.cnblogs.com/Recoder/p/5674195.html