您的位置:首页 > 其它

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

2016-07-16 20:25 344 查看
题目链接: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);

          }

    }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: