树链剖分+BIT - FZU 2082 - 过路费
树链剖分+BIT - FZU 2082 - 过路费
核心思路:
- 边权转化为点权:树上某一条边可以唯一转化为子节点的点权
- BIT维护单点修改+区间查询
注意本题有多组输入,每组样例需要重新init
#include <cstdio>
#include <vector>
#include <cstdlib>
using namespace std;
const int N = 5e4+5;
int n, m;
int a;
int b, c;
struct Node{
int v;
int d;
Node(){};
Node(int _v,int _d){
v = _v;
d = _d;
}
};
vector<Node> edges[N];
vector<Node> vec(1);
int head[N];
int fa[N];
int dep[N];
int heavy_son[N];
int dfs_id[N];
int dfs_begin[N];
int dfs_end[N];
int w[N]; // 节点i到其父节点的边的边权
int tree[N];
int dfs1(int cur, int prev, int depth){
fa[cur] = prev;
dep[cur] = depth;
int tot_size = 1, cur_size = 0,max_size = 0, max_root = 0;
for(vector<Node>::iterator it = edges[cur].begin(); it != edges[cur].end(); ++it){
if(it->v == prev) continue;
w[it->v] = it->d; // 节点i到其父节点的边的边权
cur_size = dfs1(it->v, cur, depth+1);
tot_size += cur_size;
if(cur_size > max_size){
max_size = cur_size;
max_root = it->v;
}
}
heavy_son[cur] = max_root;
return tot_size;
}
void dfs2(int cur, int prev, int head_node, int& id){
head[cur] = head_node;
dfs_id[cur] = id++;
if(heavy_son[cur]){
dfs2(heavy_son[cur], cur, head_node, id);
}
for(vector<Node>::iterator it = edges[cur].begin(); it != edges[cur].end(); ++it){
if(it->v == prev || it->v == heavy_son[cur]) continue;
dfs2(it->v, cur, it->v, id);
}
dfs_begin[cur] = dfs_id[cur];
dfs_end[cur] = id-1;
}
void build_lct(){
int id = 1;
dfs1(1, 0, 1);
dfs2(1, 0, 1, id);
}
int low_bit(int x){
return -x & x;
}
int query(int pos){
int ans = 0;
while(pos >= 1){
ans += tree[pos];
pos -= low_bit(pos);
}
return ans;
}
void modify(int pos, int v){
int delta = v - query(pos) + query(pos-1);
while(pos <= n){
tree[pos] += delta;
pos += low_bit(pos);
}
}
int query_lct(int a, int b){
int ha, hb;
int ans = 0;
while(1){
ha = head[a];
hb = head[b];
if(ha == hb){
a = dfs_id[a];
b = dfs_id[b];
if(a > b) swap(a, b);
ans += query(b) - query(a);
break;
}else{
if(dep[ha] < dep[hb]){
swap(a, b);
swap(ha, hb);
}
ans += query(dfs_id[a]) - query(dfs_id[ha]-1);
a = fa[ha];
}
}
return ans;
}
void init(int n){
for(int i = 1; i <= n; ++i){
edges[i].clear();
}
vec.clear();
vec.push_back(Node());
int head[N];
for(int i = 1; i <= n; ++i){
heavy_son[i] = 0;
}
for(int i = 0; i < n; ++i){
tree[i] = 0;
}
}
int main(){
while(scanf("%d%d", &n, &m)!=EOF){
init(n);
for(int i = 1; i < n; ++i){
scanf("%d%d%d", &a, &b, &c);
edges[a].push_back(Node(b, c));
edges[b].push_back(Node(a, c));
vec.push_back(Node(a, b));
}
build_lct();
for(int i = 1; i <= n; ++i){
modify(dfs_id[i], w[i]);
}
for(int i = 1; i < n; ++i){
if(fa[vec[i].v] != vec[i].d) swap(vec[i].v, vec[i].d);
}
while(m--){
scanf("%d%d%d", &a, &b, &c);
if(a == 0){
modify(dfs_id[vec[b].v], c);
}else{
printf("%d\n",query_lct(b, c));
}
}
}
// system("pause");
return 0;
}
/*
附自制测试用例
6 2
1 2 2
1 3 1
2 4 3
3 5 7
3 6 5
1 4 6
1 4 6
6 2
1 2 2
1 3 1
2 4 3
3 5 7
3 6 5
1 4 6
1 4 6
*/
---- suffer now and live the rest of your life as a champion ----