一眼看过去是一道赤果果的树链剖分。。。但是时间卡的实在是紧,更好的做法应该是LCA啊,待我去看看,这里先练练树链剖分。
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
using namespace std;
#define LL long long
const int N = 100005;
struct EG
{
int u, v;
} EE[N];
struct EZ
{
int v;
int next;
} eg[N*2];
int cnt;
int head[N];
void add_eg(int u,int v)
{
++cnt;
eg[cnt].v = v;
eg[cnt].next = head[u];
head[u] = cnt;
}
int dep[N], w[N], fa[N], sz[N], son[N], top[N];
void dfs_1(int v,int _fa){
fa[v] = _fa;
son[v] = 0;
sz[v] = 1;
int to;
for(int i = head[v]; ~i; i=eg[i].next){
to = eg[i].v;
if(to == _fa) continue;
dep[to] = dep[v]+1;
dfs_1(to, v);
if(sz[to] > sz[son[v]]){
son[v] = to;
}
sz[v] += sz[to];
}
}
int id;
void build_tree(int v,int tp){
w[v] = ++id;
top[v] = tp;
if(son[v] != 0) build_tree(son[v], top[v]);
int to;
for(int i = head[v]; ~i; i=eg[i].next){
to = eg[i].v;
if(to == fa[v] || to == son[v]) continue;
build_tree(to, to);
}
}
LL nd_val[N], eg_val[N];
LL ans_1[N], ans_2[N];
void upd1(int x,int y,int k)
{
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
nd_val[w[top[x]]] += k;
nd_val[w[x]+1] -= k;
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
nd_val[w[x]] += k;
nd_val[w[y]+1] -= k;
}
void upd2(int x,int y,int k)
{
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
eg_val[w[top[x]]] += k;
eg_val[w[x]+1] -= k;
x = fa[top[x]];
}
if(x == y) return;
if(dep[x] > dep[y]) swap(x, y);
eg_val[w[son[x]]] += k;
eg_val[w[y]+1] -= k;
}
int main()
{
int i, j, T, n, m;
int st = 0;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
cnt = 0;
memset(head, -1, sizeof(head));
for(i=1; i<n; ++i){
scanf("%d%d",&EE[i].u,&EE[i].v);
add_eg(EE[i].u, EE[i].v);
add_eg(EE[i].v, EE[i].u);
}
id = 0;
dfs_1(1, 1);
build_tree(1, 1);
char op[13];
int x, y, k;
memset(nd_val, 0, sizeof(nd_val));
memset(eg_val, 0, sizeof(eg_val));
while(m--){
scanf("%s%d%d%d",op,&x,&y,&k);
if(op[3] == '1'){
upd1(x, y, k);
}else{
upd2(x, y, k);
}
}
for(i=1; i<n; ++i){
if(dep[EE[i].u] > dep[EE[i].v]) swap(EE[i].u, EE[i].v);
}
LL go = 0;
for(i=1; i<=id; ++i){
go += nd_val[i];
ans_1[i] = go;
}
go = 0;
for(i=1; i<=id; ++i){
go += eg_val[i];
ans_2[i] = go;
}
printf("Case #%d:\n",++st);
for(i=1; i<=n; ++i){
if(i > 1) printf(" ");
printf("%lld",ans_1[w[i]]);
}
puts("");
for(i=1; i<n; ++i){
if(i > 1) printf(" ");
printf("%lld",ans_2[w[EE[i].v]]);
}
puts("");
}
return 0;
}