Codeforces Round #362 (Div. 2) C.Lorenzo Von Matterhorn

来源:互联网 发布:淘宝助理数据设置 编辑:程序博客网 时间:2024/05/18 13:43
题目链接:http://codeforces.com/contest/697/problem/C
题意:有1~n的n个点,对于第i个点它的2*i与2*i+1有一条无向的边。现在有两种操最,第一种是将从u到v的最短路径上所有边的 权值加上w。第二种是询问u到v最短路劲上的花费是多少。
解法:我们可以将从1开始将所有的边画出来,不难发现这就是一棵二叉树。他们的最短路径即为他们到公共父亲的距离。然后我们可以不断的将u,v中最大的除以二。我们就可以求出u,v最短路径所经过的点。u==v时,这就是他们的公共父亲。对于询问也可以同样处理。由于u,v超int了,我们可以用到map来映射。map[]映射的初始化默认值为0.
AC:

#include<algorithm>
#include<iostream>
#include<cmath>
#include<map>
#include<string>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
#define ll  __int64
map<pair<ll,ll> ,ll> m;
ll q,u,v,w,t;
pair<ll,ll>tt;
void print()
{
    cout<<tt.first<<"  "<<tt.second<<"  "<<m[tt]<<endl;
}

int main()
{
    //freopen("in.txt","r",stdin);

    m.clear();
    scanf("%I64d",&q);
    while(q--)
    {
          scanf("%I64d",&t);
          if(t==1)
          {
              scanf("%I64d%I64d%I64d",&u,&v,&w);

              while(u!=v)
              {
                if(u>v)
                {

                    tt=make_pair(u,u/2);
                    m[tt]+=w;
                    u=u/2;
                }
                else if(u<v)
                {

                    tt=make_pair(v,v/2);
                    m[tt]+=w;
                    v=v/2;
                }
               //  print();
              }
          }
          else
          {
              scanf("%I64d%I64d",&u,&v);
              ll ans=0;
               while(u!=v)
              {
                if(u>v)
                {
                    tt=make_pair(u,u/2);
                    ans+=m[tt];
                     u=u/2;
                }
                else if(u<v)
                {

                     tt=make_pair(v,v/2);
                   ans+=m[tt];
                   v=v/2;
                }
                //print();
              }
              printf("%I64d\n",ans);
          }
    }

}
0 0