Codeforces Round #362 (Div. 2) C

C. Lorenzo Von Matterhorn

题意:一初始无权的二叉树(第i歌节点有2条边 i-2i  i-2i+1),节点个数最多10^18  给出2个操作1 u v w 表示给 u->v 路径上的每一条边加上w的权值 2 u v 表示询问u->v的路径的权值和

思路:给每个节点设置2个点权 左孩子点权l 和右孩子点权r 每次操作沿路径修改点权 或累加权值和

AC代码:

#include"stdio.h"
#include"math.h"
#include"map"
#include"string.h"
#include"iostream"
#include"algorithm"
#define ll long long
using namespace std;
struct Node{
    ll l,r;
    Node(){
        l=0,r=0;
    }
};
map<ll,Node> M;
int getcc(ll x){
    int ans=0;
    while(x){
        x>>=1;
        ans++;
    }
    return ans;
}
int main(){
    ll q,f,u,v,w;
    cin>>q;
    for(int k=0; k<q; ++k){
        scanf("%lld",&f);
        if(f==1){
            scanf("%lld%lld%lld",&u,&v,&w);
            int gu=getcc(u), gv=getcc(v);
            if(gu<gv){
                swap(u,v);
                swap(gu,gv);
            }
            while(gu>gv){
                if(u&1) M[u].r+=w;
                else M[u].l+=w;
                u>>=1;
                gu--;
            }
            while(u!=v){
                if(u&1) M[u].r+=w;
                else M[u].l+=w;
                u>>=1;
                if(v&1) M[v].r+=w;
                else M[v].l+=w;
                v>>=1;
            }
        }
        else{
            scanf("%lld%lld",&u,&v);
            ll ans=0;
            int gu=getcc(u),gv=getcc(v);
            if(gu<gv){
                swap(u,v);
                swap(gu,gv);
            }
            while(gu>gv){
                if(u&1) ans+=M[u].r;
                else ans+=M[u].l;
                u>>=1;
                gu--;
            }
            while(u!=v){
                if(u&1) ans+=M[u].r;
                else ans+=M[u].l;
                if(v&1) ans+=M[v].r;
                else ans+=M[v].l;
                u>>=1,v>>=1;
            }
            cout<<ans<<endl;
        }
    }
    return 0;
}

 

posted on 2017-04-09 12:11  lazzzy  阅读(200)  评论(0编辑  收藏  举报

导航