题目地址:http://codeforces.com/problemset/problem/696/A
题意:给了一棵完全二叉树,树的每个结点权值1-1e18,两种操作。对于1操作,给了结点u,v,和权值w,从u到v的最短路径上所有的分支都加上这个权值,对于2操作,给了结点u,v,查询u到v的最短路径的分支权值和。
分析:对于两个结点,只要它们沿着根结点向上找就行,小的结点等到大的结点直到和它在一层,最后两个结点重合为止。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
map<ll,ll>ma;
void add(ll x,ll y,ll z)
{
while(x != y)
{
if(x > y)
{
ma[x] += z;
x >>= 1;
}
else
{
ma[y] += z;
y >>= 1;
}
}
}
ll sum(ll x,ll y)
{
ll res = 0;
while(x != y)
{
if(x > y)
{
res += ma[x];
x >>= 1;
}
else
{
res += ma[y];
y >>= 1;
}
}
return res;
}
int main()
{
int q;
cin>>q;
while(q--)
{
int x;
cin>>x;
if(x == 1)
{
ll u,v,w;
cin>>u>>v>>w;
add(u,v,w);
}
else
{
ll u,v;
cin>>u>>v;
cout<<sum(u,v)<<endl;
}
}
return 0;
}