cf 697C Lorenzo Von Matterhorn 思维

题目链接:https://codeforces.com/problemset/problem/697/C

两种操作:

1是对树上u,v之间的所有边的权值加上w

2是查询树上u,v之间的边权和

树是满二叉树,用map存点到其父亲的边权值,对于操作一,当u!=v时我们先更新深度最大的点到其父亲的边权值,再令其等于其父亲,不断循环直至u=v。

操作二与操作一类似

#include<iostream>
#include<algorithm>
#include<map>
#include<cmath>
using namespace std;
#define ll long long
map<ll,ll>mp;
void update(ll x,ll y,ll val)
{
    while(x!=y)
    {
        if(log(y)>log(x))swap(x,y);
        mp[x]+=val;
        x>>=1;
    }
}
ll query(ll x,ll y)
{
    ll ret=0;
    while(x!=y)
    {
        if(log(y)>log(x))swap(x,y);
        ret+=mp[x];
        x>>=1;
    }
    return ret;
}
int main()
{
    mp.clear();
    ll q,op,u,v,w;
    cin>>q;
    while(q--)
    {
        cin>>op;
        if(op==1)
        {
            cin>>v>>u>>w;
            update(v,u,w);
        }
        else
        {
            cin>>v>>u;
            cout<<query(v,u)<<endl;
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/chen99/p/11767334.html