边权下放到点权,因为一父一子(
树的计划生育)。区间取反就是\(max_{now}\)变\(-min_{pre}\),\(sum\)变\(-sum\)。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define R(a,b,c) for(register int a = (b); a <= (c); ++a)
#define nR(a,b,c) for(register int a = (b); a >= (c); --a)
#define Fill(a,b) memset(a, b, sizeof(a))
#define Swap(a,b) ((a) ^= (b) ^= (a) ^= (b))
#define ON_DEBUGG
#ifdef ON_DEBUGG
#define D_e_Line printf("\n-----------\n")
#define D_e(x) std::cout << (#x) << " : " <<x << "\n"
#define FileOpen() freopen("in.txt", "r", stdin)
#define FileSave() freopen("out.txt", "w", stdout)
#define Pause() system("pause")
#include <ctime>
#define TIME() fprintf(stderr, "\nTIME : %.3lfms\n", clock() * 1000.0 / CLOCKS_PER_SEC)
#else
#define D_e_Line ;
#define D_e(x) ;
#define FileOpen() ;
#define FilSave ;
#define Pause() ;
#define TIME() ;
#endif
struct ios {
template<typename ATP> ios& operator >> (ATP &x) {
x = 0; int f = 1; char c;
for(c = getchar(); c < '0' || c > '9'; c = getchar()) if(c == '-') f = -1;
while(c >= '0' && c <= '9') x = x * 10 + (c ^ '0'), c = getchar();
x *= f;
return *this;
}
}io;
using namespace std;
template<typename ATP> inline ATP Min(ATP a, ATP b) {
return a < b ? a : b;
}
template<typename ATP> inline ATP Max(ATP a, ATP b) {
return a > b ? a : b;
}
template<typename ATP> inline ATP Abs(ATP a) {
return a < 0 ? -a : a;
}
const int N = 2e6 + 7;
int n;
struct Edge {
int nxt, pre, w;
} e[N << 1];
int head[N], cntEdge;
inline void add(int u, int v, int w) {
e[++cntEdge] = (Edge){ head[u], v, w}, head[u] = cntEdge;
}
int val[N];
int dfn[N], dfnIdx, rnk[N], top[N], fa[N], son[N], siz[N], dep[N];
inline void DFS_First(int u, int father) {
fa[u] = father, siz[u] = 1, dep[u] = dep[father] + 1;
for(register int i = head[u]; i; i = e[i].nxt){
int v = e[i].pre;
if(v == father) continue;
val[v] = e[i].w;
DFS_First(v, u);
siz[u] += siz[v];
if(siz[v] > siz[son[u]]) son[u] = v;
}
}
inline void DFS_Second(int u, int Tp) {
top[u] = Tp, dfn[u] = ++dfnIdx, rnk[dfnIdx] = u;
if(!son[u]) return;
DFS_Second(son[u], Tp);
for(register int i = head[u]; i; i = e[i].nxt){
int v = e[i].pre;
if(v != fa[u] && v != son[u]){
DFS_Second(v, v);
}
}
}
struct Tree {
int mx, mn;
long long sum;
bool tag;
} t[N << 2];
#define ls rt << 1
#define rs rt << 1 | 1
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid +1, r
inline void Pushup(int &rt) {
t[rt].mx = Max(t[ls].mx, t[rs].mx);
t[rt].mn = Min(t[ls].mn, t[rs].mn);
t[rt].sum = t[ls].sum + t[rs].sum;
}
inline void Pushdown(int &rt) {
t[ls].sum = -t[ls].sum;
t[rs].sum = -t[rs].sum;
int tmp = t[ls].mx;
t[ls].mx = -t[ls].mn;
t[ls].mn = -tmp;
tmp = t[rs].mx;
t[rs].mx = -t[rs].mn;
t[rs].mn = -tmp;
t[ls].tag ^= 1;
t[rs].tag ^= 1;
t[rt].tag = 0;
}
inline void Build(int rt, int l, int r) {
if(l == r){
t[rt].sum = t[rt].mx = t[rt].mn = val[rnk[l]];
t[rt].tag = 0;
return;
}
int mid = (l + r) >> 1;
Build(lson), Build(rson);
Pushup(rt);
}
inline void Modify(int rt, int l, int r, int x, int w) {
if(l == r){
t[rt].sum = t[rt].mx = t[rt].mn = w;
return;
}
int mid = (l + r) >> 1;
if(t[rt].tag) Pushdown(rt);
if(x <= mid)
Modify(lson, x, w);
else
Modify(rson, x, w);
Pushup(rt);
}
inline void Updata(int rt, int l, int r, int L, int R) {
if(L <= l && r <= R){
t[rt].sum = -t[rt].sum;
int tmp = t[rt].mx;
t[rt].mx = -t[rt].mn;
t[rt].mn = -tmp;
t[rt].tag ^= 1;
return;
}
if(t[rt].tag) Pushdown(rt);
int mid = (l + r) >> 1;
if(L <= mid) Updata(lson, L, R);
if(R > mid) Updata(rson, L, R);
Pushup(rt);
}
inline long long QuerySum(int rt, int l, int r, int L, int R) {
if(L <= l && r <= R){
// D_e(t[rt].sum) ;
return t[rt].sum;
}
if(t[rt].tag) Pushdown(rt);
int mid = (l + r) >> 1;
long long sum = 0;
if(L <= mid) sum += QuerySum(lson, L, R);
if(R > mid) sum += QuerySum(rson, L, R);
return sum;
}
inline int QueryMax(int rt, int l, int r, int L, int R) {
if(L <= l && r <= R) return t[rt].mx;
if(t[rt].tag) Pushdown(rt);
int mid = (l + r) >> 1, maxx = -0x7fffffff;
if(L <= mid) maxx = Max(maxx, QueryMax(lson, L, R));
if(R > mid) maxx = Max(maxx, QueryMax(rson, L, R));
return maxx;
}
inline int QueryMin(int rt, int l, int r, int L, int R) {
if(L <= l && r <= R) return t[rt].mn;
if(t[rt].tag) Pushdown(rt);
int mid = (l + r) >> 1, minn = 0x7ffffff;
if(L <= mid) minn = Min(minn, QueryMin(lson, L, R));
if(R > mid) minn = Min(minn, QueryMin(rson, L, R));
return minn;
}
inline void PathUpdata(int x, int y) {
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) Swap(x, y);
Updata(1, 1, n, dfn[top[x]], dfn[x]);
x = fa[top[x]];
}
if(dep[x] < dep[y]) Swap(x, y);
Updata(1, 1, n, dfn[y] + 1, dfn[x]);
}
inline long long PathQuerySum(int x, int y) {
long long sum = 0;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) Swap(x, y);
sum += QuerySum(1, 1, n, dfn[top[x]], dfn[x]);
x = fa[top[x]];
}
if(dep[x] < dep[y]) Swap(x, y);
return sum + QuerySum(1, 1, n, dfn[y] + 1, dfn[x]);
}
inline int PathQueryMax(int x, int y) {
int maxx = -0x7fffffff;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) Swap(x, y);
maxx = Max(maxx, QueryMax(1, 1, n, dfn[top[x]], dfn[x]));
x = fa[top[x]];
}
if(dep[x] < dep[y]) Swap(x, y);
return Max(maxx, QueryMax(1, 1, n, dfn[y] + 1, dfn[x]));
}
inline int PathQueryMin(int x, int y) {
int minn = 0x7fffffff;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) Swap(x, y);
minn = Min(minn, QueryMin(1, 1, n, dfn[top[x]], dfn[x]));
x = fa[top[x]];
}
if(dep[x] < dep[y]) Swap(x, y);
return Min(minn, QueryMin(1, 1, n, dfn[y] + 1, dfn[x]));
}
int main() {
//FileOpen();
io >> n;
R(i,2,n){
int u, v, w;
io >> u >> v >> w;
++u, ++v;
add(u, v, w);
add(v, u, w);
}
DFS_First(1, 1);
DFS_Second(1, 1);
Build(1, 1, n);
// R(i,1,n << 2) D_e(t[i].mn);
int m;
io >> m;
char opt[7];
while(m--){
scanf("%s", opt + 1);
if(opt[1] == 'C'){ // change
int x, w;
io >> x >> w;
++x; // ++subscript
Modify(1, 1, n, dfn[x], w);
}
else if(opt[1] == 'N'){ // change section
int x, y;
io >> x >> y;
++x, ++y;
PathUpdata(x, y);
}
else if(opt[1] == 'S'){ // sum
int x, y;
io >> x >> y;
++x, ++y;
printf("%lld\n", PathQuerySum(x, y));
}
else if(opt[2] == 'A'){ // max
int x, y;
io >> x >> y;
++x, ++y;
printf("%d\n", PathQueryMax(x, y));
}
else{ // min
int x, y;
io >> x >> y;
++x, ++y;
printf("%d\n", PathQueryMin(x, y));
}
}
return 0;
}