15145641

  方法:求出最近公共祖先,使用map给他们计数,注意深度的求法。

  代码如下:

#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
using namespace std;
#define LL long long
map<LL,LL> sum;
int Get_Deep(LL x)
{
    for(int i = 0; i < 63; i++)
    {
        if((1LL<<i)<=x && (1LL<<(i+1))>x) return i+1;
    }
    return 64;
}
void F_LCA(LL x,LL y,LL w)
{
//    cout<<"deep "<<x<<" "<<Get_Deep(x)<<endl;
//    cout<<"deep "<<y<<" "<<Get_Deep(y)<<endl;
    while(Get_Deep(x) > Get_Deep(y))
    {
        sum[x] += w;
        x /= 2;
    }
    while(Get_Deep(y) > Get_Deep(x))
    {
        sum[y] += w;
        y /= 2;
    }
    while(x != y)
    {
        sum[x] += w;
        sum[y] += w;
        x /= 2;
        y /= 2;
    }
}
LL G_LCA(LL x,LL y)
{
    LL ans = 0;
    while(Get_Deep(x) > Get_Deep(y))
    {
        ans += sum[x];
        x /= 2;
    }
    while(Get_Deep(y) > Get_Deep(x))
    {
        ans += sum[y];
        y /= 2;
    }
    while(x != y)
    {
        ans += sum[x];
        ans += sum[y];
        x /= 2;
        y /= 2;
    }
    return ans;
}
int main()
{
    int q,op;
    LL u,v,w;
    cin>>q;
    sum.clear();
    while(q--)
    {
        cin>>op;
        if(op == 1)
        {
            cin>>u>>v>>w;
            F_LCA(u,v,w);
        }
        else
        {
            cin>>u>>v;
            cout<<G_LCA(u,v)<<endl;
        }
    }
    return 0;
}

 

posted on 2016-08-15 17:42  icode-xiaohu  阅读(209)  评论(0编辑  收藏  举报