题目链接:http://codeforces.com/problemset/problem/697/D
给你一个有规则的二叉树,大概有1e18个点。
有两种操作:1操作是将u到v上的路径加上w,2操作是求u到v上的路径和。
我们可以看出任意一个点到1节点的边个数不会超过64(差不多就是log2(1e18)),所以可以找最近相同祖节点的方式写。
用一条边的一个唯一的端点作为边的编号(比如1到2,那2就为这条边的编号),由于数很大,所以用map来存。
进行1操作的时候就是暴力加w至u到LCA(u,v)上的各个边,同样加w至v到LCA(u , v)上的各个边。同理,进行2操作的时候也是暴力求和。
下面这是简单的写法
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef __int64 LL; 4 map <LL , LL> cnt; 5 6 int main() 7 { 8 int n; 9 LL choose , u , v , val; 10 scanf("%d" , &n); 11 while(n--) { 12 scanf("%lld" , &choose); 13 if(choose == 1) { 14 scanf("%lld %lld %lld" , &u , &v , &val); 15 while(u != v) { 16 if(u > v) { 17 cnt[u] += val; 18 u /= 2; 19 } 20 else { 21 cnt[v] += val; 22 v /= 2; 23 } 24 } 25 } 26 else { 27 scanf("%lld %lld" , &u , &v); 28 LL res = 0; 29 while(u != v) { 30 if(u > v) { 31 res += cnt[u]; 32 u /= 2; 33 } 34 else { 35 res += cnt[v]; 36 v /= 2; 37 } 38 } 39 printf("%lld\n" , res); 40 } 41 } 42 return 0; 43 }
下面是我一开始的写法,也A了,不过有点麻烦,可以不看。
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef __int64 LL; 4 const int N = 1e3 + 5; 5 vector <int> vc; 6 vector <LL> q1[N] , q2[N] , ans1 , ans2; 7 LL x[N] , y[N] , val[N]; 8 int main() 9 { 10 int n; 11 LL choose , u , v; 12 scanf("%d" , &n); 13 for(int i = 1 ; i <= n ; ++i) { 14 scanf("%lld" , &choose); 15 if(choose == 1) { 16 scanf("%lld %lld %lld" , x + i , y + i , val + i); 17 vc.push_back(i); 18 LL num1 = x[i] , num2 = y[i]; 19 q1[i].push_back(num1) , q2[i].push_back(num2); 20 while(num1 != num2) { 21 if(num1 > num2) { 22 num1 /= 2; 23 q1[i].push_back(num1); 24 } 25 else { 26 num2 /= 2; 27 q2[i].push_back(num2); 28 } 29 } 30 } 31 else { 32 scanf("%lld %lld" , &u , &v); 33 LL temp1 = u , temp2 = v , res = 0; 34 ans1.clear() , ans2.clear(); 35 ans1.push_back(temp1) , ans2.push_back(temp2); 36 while(temp1 != temp2) { 37 if(temp1 > temp2) { 38 temp1 /= 2; 39 ans1.push_back(temp1); 40 } 41 else { 42 temp2 /= 2; 43 ans2.push_back(temp2); 44 } 45 } 46 for(int j = 0 ; j < vc.size() ; ++j) { 47 int l = 0 , r = ans1.size() - 1 , k = 0; 48 while(l + 1 <= r) { 49 for( ; k + 1 < q1[vc[j]].size() ; ++k) { 50 if(ans1[l] > q1[vc[j]][k]) 51 break; 52 if(ans1[l + 1] == q1[vc[j]][k + 1] && ans1[l] == q1[vc[j]][k]) { 53 res += val[vc[j]]; 54 } 55 } 56 l++; 57 } 58 k = 0 , l = 0 , r = ans1.size() - 1; 59 while(l + 1 <= r) { 60 for( ; k + 1 < q2[vc[j]].size() ; ++k) { 61 if(ans1[l] > q2[vc[j]][k]) 62 break; 63 if(ans1[l + 1] == q2[vc[j]][k + 1] && ans1[l] == q2[vc[j]][k]) { 64 res += val[vc[j]]; 65 } 66 } 67 l++; 68 } 69 70 l = 0 , r = ans2.size() - 1 , k = 0; 71 while(l + 1 <= r) { 72 for( ; k + 1 < q1[vc[j]].size() ; ++k) { 73 if(ans2[l] > q1[vc[j]][k]) 74 break; 75 if(ans2[l + 1] == q1[vc[j]][k + 1] && ans2[l] == q1[vc[j]][k]) { 76 res += val[vc[j]]; 77 } 78 } 79 l++; 80 } 81 k = 0 , l = 0 , r = ans2.size() - 1; 82 while(l + 1 <= r) { 83 for( ; k + 1 < q2[vc[j]].size() ; ++k) { 84 if(ans2[l] > q2[vc[j]][k]) 85 break; 86 if(ans2[l + 1] == q2[vc[j]][k + 1] && ans2[l] == q2[vc[j]][k]) { 87 res += val[vc[j]]; 88 } 89 } 90 l++; 91 } 92 } 93 printf("%lld\n" , res); 94 } 95 } 96 return 0; 97 }
时间: 2024-10-08 01:56:32