树剖裸题 = =单纯为了纪念一下我7K的代码
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
int read()
{
int n = 0, sign = 1; char c = getchar();
while(c < '0' || c > '9') { if(c == '-') sign = -1; c = getchar(); }
while(c >= '0' && c <= '9') { n = n*10 + c-'0'; c = getchar(); }
return sign * n;
}
const int Nmax = 100005;
int N, Q;
struct edge{
int v, next;
}e[Nmax * 2];
int k = 1, head[Nmax];
inline void adde(int u, int v)
{
e[k] = (edge){ v, head[u] };
head[u] = k++;
}
int fa[Nmax], size[Nmax], son[Nmax], dep[Nmax];
int w[Nmax], ed[Nmax], top[Nmax], tot;
void dfs(int u)
{
size[u] = 1;
for(int i = head[u]; i; i = e[i].next)
{
int v = e[i].v;
if(v == fa[u]) continue;
fa[v] = u; dep[v] = dep[u] + 1;
dfs(v); size[u] += size[v];
if(size[v] > size[son[u]]) son[u] = v;
}
}
void build_tree(int u, int tp)
{
top[u] = tp; w[u] = ++tot;
if(son[u]) build_tree(son[u], tp);
for(int i = head[u]; i; i = e[i].next)
{
int v = e[i].v;
if(v == fa[u] || v == son[u]) continue;
build_tree(v, v);
}
ed[u] = tot;
}
#define lc (u << 1)
#define rc (u << 1 | 1)
struct SegmentTree{
double sum[Nmax*4 + 1], mmin[Nmax*4 + 1], mmax[Nmax*4 + 1];
double lazy[Nmax*4 + 1], ad[Nmax*4 + 1];
inline void pushdown(int u, int l, int mid, int r)
{
if(lazy[u])
{
lazy[lc] = lazy[rc] = lazy[u];
ad[lc] = ad[rc] = ad[u] = 0;
mmin[lc] = mmax[lc] = lazy[u];
sum[lc] = (mid - l + 1) * lazy[u];
mmin[rc] = mmax[rc] = lazy[u];
sum[rc] = (r - mid) * lazy[u];
lazy[u] = 0;
}
if(ad[u])
{
if(lazy[lc]) lazy[lc] += ad[u]; else ad[lc] += ad[u];
if(lazy[rc]) lazy[rc] += ad[u]; ad[rc] += ad[u];
mmin[lc] += ad[u]; mmax[lc] += ad[u];
sum[lc] += (mid - l + 1) * ad[u];
mmin[rc] += ad[u]; mmax[rc] += ad[u];
sum[rc] += (r - mid) * ad[u];
ad[u] = 0;
}
}
inline void pushup(int u)
{
sum[u] = sum[lc] + sum[rc];
mmin[u] = min(mmin[lc], mmin[rc]);
mmax[u] = max(mmax[lc], mmax[rc]);
}
void change(int u, int l, int r, int L, int R, double w)
{
if(l == L && r == R)
{
ad[u] = 0;
lazy[u] = mmin[u] = mmax[u] = w;
sum[u] = (r - l + 1) * w;
return;
}
int mid = (l + r) >> 1; pushdown(u, l, mid, r);
if(R <= mid) change(lc, l, mid, L, R, w);
else if(L > mid) change(rc, mid + 1, r, L, R, w);
else{
change(lc, l, mid, L, mid, w);
change(rc, mid + 1, r, mid + 1, R, w);
}
pushup(u);
}
void add(int u, int l, int r, int L, int R, double w)
{
if(l == L && r == R)
{
if(lazy[u]) lazy[u] += w;
else ad[u] += w;
mmin[u] += w; mmax[u] += w;
sum[u] += (r - l + 1) * w;
return;
}
int mid = (l + r) >> 1; pushdown(u, l, mid, r);
if(R <= mid) add(lc, l, mid, L, R, w);
else if(L > mid) add(rc, mid + 1, r, L, R, w);
else{
add(lc, l, mid, L, mid, w);
add(rc, mid + 1, r, mid + 1, R, w);
}
pushup(u);
}
double get_sum(int u, int l, int r, int L, int R)
{
if(l == L && r == R) return sum[u];
int mid = (l + r) >> 1; pushdown(u, l, mid, r);
if(R <= mid) return get_sum(lc, l, mid, L, R);
else if(L > mid) return get_sum(rc, mid + 1, r, L, R);
else return get_sum(lc, l, mid, L, mid) + get_sum(rc, mid + 1, r, mid + 1, R);
}
double get_min(int u, int l, int r, int L, int R)
{
if(l == L && r == R) return mmin[u];
int mid = (l + r) >> 1; pushdown(u, l, mid, r);
if(R <= mid) return get_min(lc, l, mid, L, R);
else if(L > mid) return get_min(rc, mid + 1, r, L, R);
else return min(get_min(lc, l, mid, L, mid),
get_min(rc, mid + 1, r, mid + 1, R));
}
double get_max(int u, int l, int r, int L, int R)
{
if(l == L && r == R) return mmax[u];
int mid = (l + r) >> 1; pushdown(u, l, mid, r);
if(R <= mid) return get_max(lc, l, mid, L, R);
else if(L > mid) return get_max(rc, mid + 1, r, L, R);
else return max(get_max(lc, l, mid, L, mid),
get_max(rc, mid + 1, r, mid + 1, R));
}
}t;
double get_aver(int l, int r)
{
int cnt = 0; double sum = 0;
int f1 = top[l], f2 = top[r];
while(f1 != f2)
{
if(dep[f1] < dep[f2]) { swap(f1, f2); swap(l, r); }
cnt += w[l] - w[f1] + 1;
sum += t.get_sum(1, 1, tot, w[f1], w[l]);
l = fa[f1]; f1 = top[l];
}
if(dep[l] > dep[r]) swap(l, r);
cnt += w[r] - w[l] + 1;
sum += t.get_sum(1, 1, tot, w[l], w[r]);
return sum / cnt;
}
void change(int l, int r, double aver)
{
int f1 = top[l], f2 = top[r];
while(f1 != f2)
{
if(dep[f1] < dep[f2]) { swap(f1, f2); swap(l, r); }
t.change(1, 1, tot, w[f1], w[l], aver);
l = fa[f1]; f1 = top[l];
}
if(dep[l] > dep[r]) swap(l, r);
t.change(1, 1, tot, w[l], w[r], aver);
}
void add(int l, int r, double val)
{
int f1 = top[l], f2 = top[r];
while(f1 != f2)
{
if(dep[f1] < dep[f2]) { swap(f1, f2); swap(l, r); }
t.add(1, 1, tot, w[f1], w[l], val);
l = fa[f1]; f1 = top[l];
}
if(dep[l] > dep[r]) swap(l, r);
t.add(1, 1, tot, w[l], w[r], val);
}
double Max, Min, Sum;
void get_every(int l, int r)
{
Max = -1e100, Min = 1e100, Sum = 0. ;
int f1 = top[l], f2 = top[r];
while(f1 != f2)
{
if(dep[f1] < dep[f2]) { swap(f1, f2); swap(l, r); }
Max = max(Max, t.get_max(1, 1, tot, w[f1], w[l]));
Min = min(Min, t.get_min(1, 1, tot, w[f1], w[l]));
Sum += t.get_sum(1, 1, tot, w[f1], w[l]);
l = fa[f1]; f1 = top[l];
}
if(dep[l] > dep[r]) swap(l, r);
Max = max(Max, t.get_max(1, 1, tot, w[l], w[r]));
Min = min(Min, t.get_min(1, 1, tot, w[l], w[r]));
Sum += t.get_sum(1, 1, tot, w[l], w[r]);
}
int main()
{
freopen("rebd.in", "r", stdin);
freopen("rebd.out", "w", stdout);
getchar();
N = read(); Q = read();
for(int i = 1; i < N; ++i)
{
int u = read(), v = read();
adde(u, v); adde(v, u);
}
dfs(1); build_tree(1, 1);
char sign[10]; int a, b; double v;
while(Q--)
{
scanf("%s", sign);
if(!strcmp(sign, "F")) {
a = read(); b = read();
double aver = get_aver(a, b);
change(a, b, aver);
} else if(!strcmp(sign, "N")) {
a = read(); b = read();
scanf("%lf", &v);
add(a, b, v);
} else if(!strcmp(sign, "C")){
a = read(); b = read();
get_every(a, b);
printf("%.6f %.6f %.6f\n", Min, Max, Sum);
} else if(!strcmp(sign, "FF")){
a = read();
double aver = t.get_sum(1, 1, tot, w[a], ed[a]) / (ed[a] - w[a] + 1);
t.change(1, 1, tot, w[a], ed[a], aver);
} else if(!strcmp(sign, "NN")){
a = read();
scanf("%lf", &v);
t.add(1, 1, tot, w[a], ed[a], v);
} else {
a = read();
Min = t.get_min(1, 1, tot, w[a], ed[a]);
Max = t.get_max(1, 1, tot, w[a], ed[a]);
Sum = t.get_sum(1, 1, tot, w[a], ed[a]);
printf("%.6f %.6f %.6f\n", Min, Max, Sum);
}
//for(int i = 1; i <= 13; ++i) printf("%d : %.6f %.6f %.6f\n", i, t.mmin[i], t.mmax[i], t.sum[i]);
//puts("");
}
return 0;
}