#include <algorithm> #include <iostream> #include <cstring> #include <iomanip> #include <cstdlib> #include <sstream> #include <cstdio> #include <string> #include <vector> #include <cctype> #include <stack> #include <queue> #include <deque> #include <cmath> #include <map> #include <set>
#define I inline #define ll long long #define pb push_back #define MP make_pair #define ull unsigned long long #define PII pair<int , int> #define PIL pair<int , long long> #define PSL pair<string , long long> #define PLL pair<long long , long long> #define all(x) (x).begin() , (x).end() #define copy(a , b) memcpy(a , b , sizeof(b)) #define clean(a , b) memset(a , b , sizeof(a)) #define rep(i , l , r) for (int i = (l); i <= (r); i ++) #define per(i , r , l) for (int i = (r); i >= (l); i --) #define PE(i , x) for(int i = head[x]; i; i = edge[i].last) #define DEBUG(x) std :: cerr << #x << '=' << x << std :: endl
using namespace std;
const int N = 10001; const int M = 200001; const int HA = 998244353; const int INF = 2147483647; const long long INFL = 9223372036854775807;
struct Edge{ int to , last , dis; }edge[M << 1];
int edge_num; int head[M << 1];
I void add_edge(int from , int to , int dis){ edge[++ edge_num] = (Edge){to , head[from] , dis}; head[from] = edge_num; edge[++ edge_num] = (Edge){from , head[to] , dis}; head[to] = edge_num; }
int dep[M] , fa[M] , son[M] , size[M] , val[M];
int dfs1(int x , int f , int deep){ dep[x] = deep; fa[x] = f; int maxn = -1; PE(i , x){ int to = edge[i].to , dis = edge[i].dis; if(to == f) continue; val[to] = dis; size[x] += dfs1(to , x , deep + 1); if(size[to] > maxn){ maxn = size[to]; son[x] = to; } } return size[x]; }
int tp[M] , dfn[M] , a[M] , cnt;
void dfs2(int x , int topf){ dfn[x] = ++ cnt; a[cnt] = val[x]; tp[x] = topf; if(!son[x]) return; dfs2(son[x] , topf); PE(i , x){ int to = edge[i].to; if(!dfn[to]){ dfs2(to , to); } } }
namespace Segment_tree{ #define lson(x) x << 1 #define rson(x) x << 1 | 1
struct Node{ int l , r , len; int num , add , maxn , minn , opo; }node[M << 2];
I void pushup(int x){ node[x].num = (node[lson(x)].num + node[rson(x)].num); node[x].maxn = max(node[lson(x)].maxn , node[rson(x)].maxn); node[x].minn = min(node[lson(x)].minn , node[rson(x)].minn); }
I void pushdown(int x){ if(node[x].opo != 1){ node[lson(x)].opo *= -1; node[lson(x)].num *= -1; node[rson(x)].opo *= -1; node[rson(x)].num *= -1; int lmax = node[lson(x)].maxn , lmin = node[lson(x)].minn; int rmax = node[rson(x)].maxn , rmin = node[rson(x)].minn; node[lson(x)].maxn = -lmin; node[lson(x)].minn = -lmax; node[rson(x)].maxn = -rmin; node[rson(x)].minn = -rmax; node[x].opo = 1; } if(node[x].add != 0){ node[lson(x)].add += node[x].add; node[lson(x)].num += node[x].add * node[lson(x)].len; node[rson(x)].add += node[x].add; node[rson(x)].num += node[x].add * node[rson(x)].len; node[x].add = 0; } }
void build(int x , int l , int r){ node[x].l = l; node[x].r = r; node[x].len = (r - l + 1); node[x].opo = 1; if(l == r){ node[x].num = node[x].maxn = node[x].minn = a[l]; return ; } int mid = (node[x].l + node[x].r) >> 1; build(lson(x) , l , mid); build(rson(x) , mid + 1 , r); pushup(x); }
void point_change(int x , int q, int change){ if(node[x].l == node[x].r){ node[x].num = change; node[x].add = 0; node[x].maxn = node[x].minn = change; return; } pushdown(x); int mid = (node[x].l + node[x].r) >> 1; if(q <= mid){ point_change(lson(x) , q , change); } else{ point_change(rson(x) , q , change); } pushup(x); }
void range_add(int x , int ql , int qr , int add){ if(ql <= node[x].l && node[x].r <= qr){ node[x].add += add; node[x].num += node[x].len * add; return ; } pushdown(x); int mid = (node[x].l + node[x].r) >> 1; if(ql <= mid){ range_add(lson(x) , ql , qr , add); } if(mid + 1 <= qr){ range_add(rson(x) , ql , qr , add); } pushup(x); }
void range_opposite(int x , int ql , int qr){ if(ql <= node[x].l && node[x].r <= qr){ node[x].opo *= -1; node[x].num *= -1; int maxn = node[x].maxn , minn = node[x].minn; node[x].maxn = -minn; node[x].minn = -maxn; return ; } pushdown(x); int mid = (node[x].l + node[x].r) >> 1; if(ql <= mid){ range_opposite(lson(x) , ql , qr); } if(mid + 1 <= qr){ range_opposite(rson(x) , ql , qr); } pushup(x); }
int range_query(int x , int ql , int qr){ if(ql <= node[x].l && node[x].r <= qr){ return node[x].num; } pushdown(x); int mid = (node[x].l + node[x].r) >> 1 , ans = 0; if(ql <= mid){ ans += range_query(lson(x) , ql , qr); } if(mid + 1 <= qr){ ans += range_query(rson(x) , ql , qr); } return ans; }
int range_max(int x , int ql , int qr){ if(ql <= node[x].l && node[x].r <= qr){ return node[x].maxn; } pushdown(x); int mid = (node[x].l + node[x].r) >> 1 , ans = -0x3f3f3f3f; if(ql <= mid){ ans = max(ans , range_max(lson(x) , ql , qr)); } if(mid + 1 <= qr){ ans = max(ans , range_max(rson(x) , ql , qr)); } return ans; }
int range_min(int x , int ql , int qr){ if(ql <= node[x].l && node[x].r <= qr){ return node[x].minn; } pushdown(x); int mid = (node[x].l + node[x].r) >> 1 , ans = 0x3f3f3f3f; if(ql <= mid){ ans = min(ans , range_min(lson(x) , ql , qr)); } if(mid + 1 <= qr){ ans = min(ans , range_min(rson(x) , ql , qr)); } return ans; }
#undef lson #undef rson }
void tree_opposite(int x , int y){ while(tp[x] != tp[y]){ if(dep[tp[x]] < dep[tp[y]]){ swap(x , y); } Segment_tree :: range_opposite(1 , dfn[tp[x]] , dfn[x]); x = fa[tp[x]]; } if(x != y){ if(dep[x] > dep[y]) swap(x , y); Segment_tree :: range_opposite(1 , dfn[x] + 1 , dfn[y]); } }
int tree_query(int x , int y){ int ans = 0; while(tp[x] != tp[y]){ if(dep[tp[x]] < dep[tp[y]]){ swap(x , y); } ans += Segment_tree :: range_query(1 , dfn[tp[x]] , dfn[x]); x = fa[tp[x]]; } if(x != y){ if(dep[x] > dep[y]) swap(x , y); ans += Segment_tree :: range_query(1 , dfn[x] + 1 , dfn[y]); } return ans; }
int tree_max(int x , int y){ int ans = -0x3f3f3f3f; while(tp[x] != tp[y]){ if(dep[tp[x]] < dep[tp[y]]){ swap(x , y); } ans = max(ans , Segment_tree :: range_max(1 , dfn[tp[x]] , dfn[x])); x = fa[tp[x]]; } if(x != y){ if(dep[x] > dep[y]) swap(x , y); ans = max(ans , Segment_tree :: range_max(1 , dfn[x] + 1 , dfn[y])); } return ans; }
int tree_min(int x , int y){ int ans = 0x3f3f3f3f; while(tp[x] != tp[y]){ if(dep[tp[x]] < dep[tp[y]]){ swap(x , y); } ans = min(ans , Segment_tree :: range_min(1 , dfn[tp[x]] , dfn[x])); x = fa[tp[x]]; } if(x != y){ if(dep[x] > dep[y]) swap(x , y); ans = min(ans , Segment_tree :: range_min(1 , dfn[x] + 1 , dfn[y])); } return ans; }
int from1[M] , to1[M];
void change(int x , int y , int val){ if(dep[x] > dep[y]) swap(x , y); Segment_tree :: point_change(1 , dfn[y] , val); }
int main() { #ifdef LOCAL freopen("P1505_4.in" , "r" , stdin); freopen("P1505_4.out" , "w" , stdout); #endif int n; scanf("%d" , &n); int u , v , d; rep(i , 1 , n - 1){ scanf("%d%d%d" , &u , &v , &d); u ++; v ++; add_edge(u , v , d); from1[i] = u; to1[i] = v; } dfs1(1 , 0 , 1); dfs2(1 , 1); Segment_tree :: build(1 , 1 , n);
int m; scanf("%d" , &m); char opt[10]; int x , y; while(m --){ scanf("%s" , opt); scanf("%d%d" , &x , &y); if(opt[0] == 'C'){ change(from1[x] , to1[x] , y); } else if(opt[0] == 'N'){ x ++; y ++; tree_opposite(x , y); } else if(opt[0] == 'S'){ x ++; y ++; printf("%d\n" , tree_query(x , y)); } else{ if(opt[1] == 'A'){ x ++ , y ++; printf("%d\n" , tree_max(x , y)); } else if(opt[1] == 'I'){ x ++ , y ++; printf("%d\n" , tree_min(x , y)); } } }
return 0; }
|