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\n" , 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\n" , res);
94         }
95     }
96     return 0;
97 }
时间: 2024-10-08 01:56:32

Codeforces Round #362 (Div. 2) C. Lorenzo Von Matterhorn (类似LCA)的相关文章

Codeforces Round #362 (Div. 2) C. Lorenzo Von Matterhorn LCA(最近公共祖先)

C. Lorenzo Von Matterhorn time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Barney lives in NYC. NYC has infinite number of intersections numbered with positive integers starting from 1. Ther

Codeforces Round #362 (Div. 2) ABCDE

A. Pineapple Incident 题解: 水题...注意没有t+1这种情形 代码: #include<bits/stdc++.h> #define pb push_back #define mp make_pair #define se second #define fs first #define ll long long using namespace std; const int INF=1e9+10; const int maxn=1000000+5; ll read() {

Codeforces Round #362 (Div. 1) B. Puzzles 树形dp,概率

题目链接: http://codeforces.com/problemset/problem/696/B 题意: 一个树,dfs遍历子树的顺序是随机的.所对应的子树的dfs序也会不同.输出每个节点的dfs序的期望 思路: http://www.cnblogs.com/01world/p/5795498.html 假设四个子节点为A,B,C,D,因为排列等可能,所以A在B前面的概率跟A在B后面的概率相等,C和D对于A而言一样.所以遍历A的时间期望就是( t(B) + t(C) + t(D) )/2

【转载】【树形DP】【数学期望】Codeforces Round #362 (Div. 2) D.Puzzles

期望计算的套路: 1.定义:算出所有测试值的和,除以测试次数. 2.定义:算出所有值出现的概率与其乘积之和. 3.用前一步的期望,加上两者的期望距离,递推出来. 题意: 一个树,dfs遍历子树的顺序是随机的.所对应的子树的dfs序也会不同.输出每个节点的dfs序的期望   思路: 分析一颗子树: 当前已知节点1的期望为1.0 ->anw[1]=1.0 需要通过节点1递推出节点2.4.5的期望值 1的儿子分别是2.4.5,那么dfs序所有可能的排列是6种: 1:1-2-4-5  (2.4.5节点的

D. Puzzles(Codeforces Round #362 (Div. 2))

D. Puzzles Barney lives in country USC (United States of Charzeh). USC has n cities numbered from 1 through n and n - 1 roads between them. Cities and roads of USC form a rooted tree (Barney's not sure why it is rooted). Root of the tree is the city

Codeforces Round #292 (Div. 1) B. Drazil and Tiles (类似拓扑)

题目链接:http://codeforces.com/problemset/problem/516/B 一个n*m的方格,'*'不能填.给你很多个1*2的尖括号,问你是否能用唯一填法填满方格. 类似topsort,'.'与上下左右的'.',的相连.从度为1的点作为突破口. 1 //#pragma comment(linker, "/STACK:102400000, 102400000") 2 #include <algorithm> 3 #include <iostr

【CodeForces 697C】Lorenzo Von Matterhorn(LCA)

Least Common Ancestors 节点范围是1~1e18,至多1000次询问. 只要不断让深的节点退一层(>>1)就能到达LCA. 用点来存边权,用map储存节点和父亲连边的权值. #include<cstdio> #include<map> #define ll long long using namespace std; map<ll,ll>m; ll u,v,w; void add(){ while(u!=v){ if(u<v){ m

Codeforces Round #143 (Div. 2) E. Cactus 无向图缩环+LCA

E. Cactus A connected undirected graph is called a vertex cactus, if each vertex of this graph belongs to at most one simple cycle. A simple cycle in a undirected graph is a sequence of distinct vertices v1, v2, ..., vt (t > 2), such that for any i (

CodeForces 696A Lorenzo Von Matterhorn (LCA + map)

方法:求出最近公共祖先,使用map给他们计数,注意深度的求法. 代码如下: #include<iostream> #include<cstdio> #include<map> #include<cstring> using namespace std; #define LL long long map<LL,LL> sum; int Get_Deep(LL x) { for(int i = 0; i < 63; i++) { if((1LL