2018-03-16
http://codeforces.com/problemset/problem/697/C
题意:先给出q次操作,当输入1的时候,表示一棵完全二叉树的两个节点u、v之间最短路径的权值全部加上w,当输入2的时候,表示询问这棵树的u到v节点间最短路径的权值之和。
解析:一棵二叉树!从任意一个点出发往上爬最多只要64步就能爬到顶点了,可以暴力。然后就是LCA思想。存入权值和计算最短路径的权值一样思路。为什么map?因为数值很大,不能用数组存,所以一边建点一边存入权值(加到对应一对点中较大点的map上)。
复杂度:O(q*log(n)*log(n))其中map的复杂度是log(n)
Code:
1 #include<string.h> 2 #include<cmath> 3 #include<cstdio> 4 #include<algorithm> 5 #include<iostream> 6 #include<vector> 7 #include<queue> 8 #include<string> 9 #include<map> //map 10 using namespace std; 11 #define MAX 0x3f3f3f3f 12 #define fi first 13 #define se second 14 #define ll long long 15 16 map < ll,ll > mp; //map 因为数据太大了,不能使用数组 17 18 int main() 19 { 20 int q; 21 ll t,v,u,w; 22 while(cin>>q) 23 { 24 25 for(int i=1;i<=q;i++) 26 { 27 /*cin>>t>>v>>u>>w;*/ 28 cin>>t; 29 if(t==1) 30 { 31 cin>>v>>u>>w; 32 while(v!=u) 33 { 34 if(v < u) 35 { 36 swap(v,u); 37 } 38 39 mp[v]+=w; 40 v/=2; //这个点一定是从它的/2过来的 41 } 42 } 43 else 44 { 45 cin>>v>>u; 46 ll ans=0; 47 while(v!=u) 48 { 49 if(v<u) 50 { 51 swap(v,u); 52 } 53 ans+=mp[v]; 54 v/=2; 55 } 56 cout<<ans<<endl; 57 } 58 59 } 60 61 } 62 63 }