传送门: CodeForces - 697C
原创--原创--原创
第一次自己A了一道感觉有点难度的题;
题意:在一个类似于二叉树的图上,1 : u ,v,w 表示从u到v的所以路都加上w的费用;
2 : u,v 输出u,v间的花费;
思路:自己看这个图,一直想写线段树,后来想想LCA求最近公共祖先,一步一步向上跳的思想还可以,
就用 每个点 表示这个点到父节点所需要的花费;计算的时候,和求LCA相似,累加到最近公共祖先的花费;
还有就是用map< ll , ll >存每个节点的信息;
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <string> #include <vector> #include <map> using namespace std; typedef long long ll; map<ll,ll>mp; int q; int log2(ll x) { int res=0; while(x>1) { x/=2; res++; } return res+1; } int main(){ //freopen("in","r",stdin); scanf("%d",&q); while(q--) { int tag; ll u,v,w; scanf("%d",&tag); if(tag==1) { scanf("%lld%lld%lld",&u,&v,&w); if(log2(u)<log2(v))swap(u,v); while(log2(u)>log2(v)) { mp[u]+=w; u/=2; } while(u!=v) { mp[u]+=w; mp[v]+=w; u=u/2; v=v/2; } } else { scanf("%lld%lld",&u,&v); ll ans = 0; if(log2(u)<log2(v))swap(u,v); while(log2(u)>log2(v)) { ans+=mp[u]; u/=2; } while(u!=v) { ans+=mp[u]; ans+=mp[v]; u=u/2; v=v/2; } // if(u!=1)ans+=mp[u]; printf("%lld ",ans); // if(ans==94)cout<<"*"<<mp[6]<<endl; } } return 0; }