伸展树暴力搞一下,反正只要是平衡树都能过,思路是把u到v路径上的结点加入到树中,查询直接去树里查就好了,每次更新最多120个结点而已(120是它的上界的样子没有具体去算),最多1000次查询也就是最多12000次更新。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <list>
#include <stack>
#include <cstring>
#include <queue>
#include <map>
#include <string>
using namespace std;
#define MAX 100005
#define ll long long
#define INF 0x3f3f3f3f
#define mod 1000000007
int q;
ll x, y, z;
struct splayTree {
ll v, c;
splayTree* son[2];
splayTree* father;
splayTree(ll value,ll w,splayTree* f) {
son[0] = son[1] = NULL;
father = f;
v = value, c = w;
}
};
splayTree* root = new splayTree(0, 0, NULL);
int judgeson(splayTree* p, splayTree* f) {
return f->son[1] == p;
}
void rotate(splayTree* p) {
splayTree* f = p->father;
splayTree* g = f->father;
int u = judgeson(p, f);
if (g != NULL) {
int v = judgeson(f, g);
g->son[v] = p;
}
if (f == root) {
root = p;
}
p->father = g;
f->son[u] = p->son[u ^ 1];
if (p->son[u ^ 1] != NULL) {
p->son[u ^ 1]->father = f;
}
p->son[u ^ 1] = f;
f->father = p;
}
void Splay(splayTree* p,splayTree* r) {
while (p->father != r) {
splayTree* f = p->father;
splayTree* g = f->father;
if (g == r) {
rotate(p);
return;
}
int u = judgeson(p, f);
int v = judgeson(f, g);
if (u ^ v) {
rotate(f);
rotate(p);
}
else {
rotate(p);
rotate(p);
}
}
}
void insert(ll value,ll w,splayTree* p) {
for (; p != NULL; p = p->son[p->v < value]) {
if (p->v == value) {
p->c += w;
Splay(p, NULL);
return;
}
if (p->son[p->v < value] == NULL) {
p->son[p->v < value] = new splayTree(value,w,p);
Splay(p,NULL);
return;
}
}
}
ll query(ll value, splayTree* p) {
for (; p != NULL; p = p->son[p->v < value]) {
if (p->v == value) {
return p->c;
}
}
return 0;
}
int main()
{
// freopen("a.txt", "r", stdin);
// freopen("b.txt", "w", stdout);
int t;
cin >> q;
for (int i = 0; i < q; ++i) {
scanf("%d", &t);
if (t == 1) {
scanf("%I64d%I64d%I64d", &x, &y, &z);
for (; x != y;) {
if (x > y) {
insert(x, z, root);
x >>= 1;
}
else {
insert(y, z, root);
y >>= 1;
}
}
}
else {
scanf("%I64d%I64d", &x, &y);
ll sum = 0;
for (; x != y;) {
if (x > y) {
sum += query(x, root);
x >>= 1;
}
else {
sum += query(y, root);
y >>= 1;
}
}
printf("%I64d\n", sum);
}
}
return 0;
}