Codeforces 697C
题目链接:http://codeforces.com/problemset/problem/697/C
题意:给了一棵二叉树,二叉树每个结点的编号与同层数的满二叉树相同,注意树的结点范围是1e18,需要用到long long以及map。询问中有两种操作。第一种,给定结点u,v以及一个权值w,从u到v的最短路径上所有的结点都加上这个权值;第二种,给定结点u,v,查询u到v的最短路径上的所有结点的权值和。
分析:由于是二叉树的结点编号与同层数的满二叉树相同,对于每个结点,从给定的结点位置开始,将结点位置整除二就能得到最短路径上下一个点的位置,直到两个结点相遇为止,一直对途经的结点进行加权/求和操作即可。可以说是最基础的lca思想吧。
#include <algorithm> //swap
#include <iostream>
#include <cstring>
#include <map>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 200010;
int i, j, k;
int m, n;
// u/v 1e18
map<ll, ll>mp;
int main() {
scanf("%d", &n);
mp.clear();
for (i = 0; i < n; i++) {
int ch;
scanf("%d", &ch);
ll u, v, w;
if (ch == 1) {
scanf("%lld%lld%lld", &u, &v, &w);
while (u != v) {
if (u < v) {
mp[v] += w;
v /= 2;
}
else {
mp[u] += w;
u /= 2;
}
}
}
else {
scanf("%lld%lld", &u, &v);
ll res = 0;
while (u != v) {
if (u < v) {
res += mp[v];
v /= 2;
}
else {
res += mp[u];
u /= 2;
}
}
printf("%lld\n", res);
}
}
return 0;
}