题目链接: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; }