codeforces基础题——#362(div2)C

来源:互联网 发布:sql修复工具 编辑:程序博客网 时间:2024/05/22 14:16

#362(Div 2) C

题目大意: 有一颗无穷大的二叉树, 以编号1为的点根, 编号为i的点的儿子分别为i * 2, i * 2 + 1,     有q(1 <= q <= 1000)次操作:    1.  将点u到v的路径 上所有边的权值加w;    2.  查询u到v路径上边的权值和;

1 <= u, v <= 1018, w <= 109

题解    这题作为C题感觉有些水, 点数太多了, 而只有极少的点有用, 所以直接上map, 然后用类似LCA的方法直接搞一搞就行了。
#include <cstdio>#include <map>using namespace std;typedef long long LL;int log(LL x){    int l = 0;    while(x) x >>= 1, l ++;    return l;}map<LL, LL>m;int main(){    int q, ty, c;    LL a, b;    scanf("%d", &q);    for (int i = 1; i <= q; i ++) {        scanf("%d %I64d %I64d", &ty, &a, &b);        if (ty == 1) scanf("%d", &c);        int l1 = log(a), l2 = log(b);        LL sum = 0;        while(l1 > l2){             if (ty == 1) m[a] += c;            else sum += m[a];            a = a / 2, l1 --;        }        while(l1 < l2){            if (ty == 1) m[b] += c;            else sum += m[b];             b = b / 2, l2 --;        }        while(a != b){            if (ty == 1) m[a] += c, m[b] += c;            else sum += m[a] + m[b];             a = a / 2, b = b / 2;        }        if (ty == 2) printf("%I64d\n", sum);    }    return 0;}
0 0
原创粉丝点击