P1505 [國家集訓隊]旅遊

\(\text{很顯然這題是個樹剖。。。若是您不會樹剖 請去模板題}\)node

\(\text{修改1:單點修改。。}\)c++

\(\text{修改2:區間乘-1 這樣的話最大值須要變成最小值的負數 最小值要變成最大值的負數}\)git

\(\text{查詢1:區間求和}\)ui

\(\text{查詢2:區間最大值}\)spa

\(\text{查詢3:區間最小值}\)code

\(\text{因此很顯然咱們能夠發現這個就是一個普通的樹剖}\)get

\(\text{這題的碼量巨大。。我打了20min 可是調了一個小時。。。}\)string

\(\text{問題在於 最小值 最大值的處理 以及 懶標記 我在求最大最小值的時候忘記處理了。。。這些都是比較弱智的問題。。}\)it

\(\huge \mathcal{Code}\)模板

//Isaunoya
#include<bits/stdc++.h>
using namespace std ;
inline int read() {
    register int x = 0 ;
    register int f = 1 ;
    register char c = getchar() ;
    for( ; ! isdigit(c) ; c = getchar()) if(c == '-') f = -1 ;
    for( ; isdigit(c) ; c = getchar()) x = (x << 1) + (x << 3) + (c & 15) ;
    return x * f ;
}
int st[105] ;
template < typename T > inline void write(T x , char c = '\n') {
    int tp = 0 ;
    if(x == 0) return (void) puts("0") ;
    if(x < 0) putchar('-') , x = -x ;
    for( ; x ; x /= 10) st[++ tp] = x % 10 ;
    for( ; tp ; tp --) putchar(st[tp] + '0') ;
    putchar(c) ;
}
//#define Online_Judge
//#define int long long
#define swap(x , y) x ^= y ^= x ^= y
int n ;
const static int N = 200000 + 5 ;
int a[N] ;
namespace SegTree {
    struct Node {
        int mn ; // the min
        int mx ; // the max
        int add ; // the sum
        int lazy ; // the sign
    };
    Node t[N << 2] ;
    inline void Push_down(int rt) {
        if(t[rt].lazy) {
            t[rt << 1].add = - t[rt << 1].add ;
            t[rt << 1 | 1].add = - t[rt << 1 | 1].add ;
            t[rt << 1].lazy ^= 1 ;
            t[rt << 1 | 1].lazy ^= 1 ;
            swap(t[rt << 1].mx , t[rt << 1].mn) ;
            swap(t[rt << 1 | 1].mx , t[rt << 1 | 1].mn) ;
            t[rt << 1].mx = - t[rt << 1].mx ;
            t[rt << 1].mn = - t[rt << 1].mn ;
            t[rt << 1 | 1].mx = - t[rt << 1 | 1].mx ;
            t[rt << 1 | 1].mn = - t[rt << 1 | 1].mn ;
            t[rt].lazy = 0 ;
        }
        return ;
    }
    //==============================================push_down
    inline void Push_Up(int rt) {
        t[rt].add = t[rt << 1].add + t[rt << 1 | 1].add ;
        t[rt].mx = max(t[rt << 1].mx , t[rt << 1 | 1].mx) ;
        t[rt].mn = min(t[rt << 1].mn , t[rt << 1 | 1].mn) ;
        return ;
    }
    //==============================================push_up
    inline void build(int l , int r , int rt) {
        if(l == r) {
            t[rt].add = t[rt].mn = t[rt].mx = a[l] ;
            return ;
        }
        int mid = l + r >> 1 ;
        build(l , mid , rt << 1) ;
        build(mid + 1 , r , rt << 1 | 1) ;
        Push_Up(rt) ;
    }
    //==============================================build
    inline void Add(int x , int l , int r , int rt , int val) {
        if(l == r) {
            t[rt].add = t[rt].mn = t[rt].mx = val ;
            return ;
        }
        int mid = l + r >> 1 ;
        Push_down(rt) ;
        if(x <= mid) Add(x , l , mid , rt << 1 , val) ;
        else Add(x , mid + 1 , r , rt << 1 | 1 , val) ;
        Push_Up(rt) ;
    }
    //==============================================change x - > val
    inline void Change(int a , int b , int l , int r , int rt) {
        if(a > r || b < l) return ;
        if(a <= l && r <= b) {
            t[rt].add = - t[rt].add ;
            t[rt].lazy ^= 1 ;
            swap(t[rt].mx , t[rt].mn) ;
            t[rt].mx = - t[rt].mx ;
            t[rt].mn = - t[rt].mn ;
            return ;
        }
        int mid = l + r >> 1 ;
        Push_down(rt) ;
        Change(a , b , l , mid , rt << 1) ;
        Change(a , b , mid + 1 , r , rt << 1 | 1) ;
        Push_Up(rt) ;
    }
    //===============================================change x - > -x
    inline int Sum(int a , int b , int l , int r , int rt) {
        if(a > r || b < l) return 0 ;
        if(a <= l && r <= b) return t[rt].add ;
        int mid = l + r >> 1 ;
        Push_down(rt) ;
        int ans = 0 ;
        ans += Sum(a , b , l , mid , rt << 1 ) ;
        ans += Sum(a , b , mid + 1 , r , rt << 1 | 1) ;
        Push_Up(rt) ;
        return ans ;
    }
    //====================================================== a - > b sum
    inline int Min(int L , int R , int l , int r , int rt) {
        if(L > r || R < l) return INT_MAX ;
        if(L <= l && r <= R) return t[rt].mn ;
        int ans = INT_MAX ;
        int mid = l + r >> 1 ;
        Push_down(rt) ;
        if(L <= mid) ans = min(ans , Min(L , R , l , mid , rt << 1)) ;
        if(R > mid) ans = min(ans , Min(L , R, mid + 1 , r , rt << 1 | 1)) ;
        Push_Up(rt) ;
        return ans ;
    }
    //====================================================== a - > b min
    inline int Max(int L , int R , int l , int r , int rt) {
        if(L > r || R < l) return INT_MIN ;
        if(L <= l && r <= R) return t[rt].mx ;
        int ans = INT_MIN ;
        int mid = l + r >> 1 ;
        Push_down(rt) ;
        if(L <= mid) ans = max(ans , Max(L , R , l , mid , rt << 1)) ;
        if(R > mid) ans = max(ans , Max(L , R, mid + 1 , r , rt << 1 | 1)) ;
        Push_Up(rt) ;
        return ans ;
    }
    //====================================================== a - > b max
}
//===========================================================SegTree
namespace SLPF {
    struct node {
        int v ;
        int nxt ;
        int w ;
    };
    int fa[N] ; int id[N] ; int son[N] ;
    int size[N] ; int d[N] ; int top[N] ;
    int fst[N] ;
    node e[N << 1] ;
    int tot = 0 ;
    int head[N] ; int cnt = 0 ;
    inline void Add_Edge(int u , int v , int w) {
        e[++ cnt].v = v ;
        e[cnt].nxt = head[u] ;
        e[cnt].w = w ;
        head[u] = cnt ;
        return ;
    }
    inline void Dfs1(int u) {
        size[u] = 1 ;
        for(register int i = head[u] ; i ; i = e[i].nxt) {
            int v = e[i].v ;
            if(v ^ fa[u]) {
                d[v] = d[u] + 1 ;
                fa[v] = u ;
                fst[v] = e[i].w ;
                Dfs1(v) ;
                size[u] += size[v] ;
                if(size[v] > size[son[u]]) son[u] = v ;
            }
        }
    }
    inline void Dfs2(int u , int t) {
        id[u] = ++ tot ;
        top[u] = t ;
        a[tot] = fst[u] ;
        if(son[u]) Dfs2(son[u] , t) ;
        for(register int i = head[u] ; i ; i = e[i].nxt) {
            int v = e[i].v ;
            if(v ^ fa[u] && v ^ son[u]) Dfs2(v , v) ;
        }
    }
    //========================================================Dfs1 && Dfs2

    inline void Change_Range(int x , int y) {
        int fx = top[x] ;
        int fy = top[y] ;
        while(fx ^ fy) {
            if(d[fx] < d[fy]) swap(x , y) , swap(fx , fy) ;
            SegTree::Change(id[fx] , id[x] , 1 , tot , 1) ;
            x = fa[fx] ;
            fx = top[x] ;
        }
        if(id[x] > id[y]) swap(x , y) ;
        SegTree::Change(id[x] + 1 , id[y] , 1 , tot , 1) ;
    }
    inline int Query_Sum(int x , int y) {
        int fx = top[x] ;
        int fy = top[y] ;
        int ans = 0 ;
        while(fx ^ fy) {
            if(d[fx] < d[fy]) swap(x , y) , swap(fx , fy) ;
            ans += SegTree::Sum(id[fx] , id[x] , 1 , tot , 1) ;
            x = fa[fx] ;
            fx = top[x] ;
        }
        if(id[x] > id[y]) swap(x , y) ;
        ans += SegTree::Sum(id[x] + 1 , id[y] , 1 , tot , 1) ;
        return ans ;
    }
    inline int Query_Min(int x , int y) {
        int fx = top[x] ;
        int fy = top[y] ;
        int ans = INT_MAX ;
        while(fx ^ fy) {
            if(d[fx] < d[fy]) swap(x , y) , swap(fx , fy) ;
            ans = min(ans , SegTree::Min(id[fx] , id[x] , 1 , tot , 1)) ;
            x = fa[fx] ;
            fx = top[x] ;
        }
        if(id[x] > id[y]) swap(x , y) ;
        ans = min(ans , SegTree::Min(id[x] + 1 , id[y] , 1 , tot , 1)) ;
        return ans ;
    }
    inline int Query_Max(int x , int y) {
        int fx = top[x] ;
        int fy = top[y] ;
        int ans = INT_MIN ;
        while(fx ^ fy) {
            if(d[fx] < d[fy]) swap(x , y) , swap(fx , fy) ;
            ans = max(ans , SegTree::Max(id[fx] , id[x] , 1 , tot , 1)) ;
            x = fa[fx] ;
            fx = top[x] ;
        }
        if(id[x] > id[y]) swap(x , y) ;
        ans = max(ans , SegTree::Max(id[x] + 1 , id[y] , 1 , tot , 1)) ;
        return ans ;
    }
}
using namespace SLPF ;
inline int getopt() {
    string s = "" ;
    register char c = getchar() ;
    while(isspace(c)) c = getchar() ;
    while(! isspace(c)) {
        s += c ;
        c = getchar() ;
    }
    if(s == "C") return 0 ;
    if(s == "N") return 1 ;
    if(s == "SUM") return 2 ;
    if(s == "MAX") return 3 ;
    if(s == "MIN") return 4 ;
}
signed main() {
#ifdef Online_Judge
    freopen("testdata.in" , "r" , stdin) ;
    freopen("testdata2.out" , "w" , stdout) ;
#endif
    n = read() ;
    for(register int i = 1 ; i <= n - 1 ; i ++) {
        int u = read() , v = read() , w = read() ;
        u ++ , v ++ ;
        Add_Edge(u , v , w) ;
        Add_Edge(v , u , w) ;
    }
    Dfs1(1) ;
    Dfs2(1 , 0) ;
    SegTree::build(1 , n , 1) ;
    for(register int t = read() ; t -- ; ) {
        int opt = getopt() ;
//      write(opt) ;
        if(opt == 0) {
            int x = read() , y = read() ;
            x ++ ;
            SegTree::Add(id[x] , 1 , n , 1 , y) ;
        }
        if(opt == 1) {
            int x = read() , y = read() ;
            x ++ , y ++ ;
            Change_Range(x , y) ;
        }
        if(opt == 2) {
            int x = read() , y = read() ;
            x ++ , y ++ ;
            write(Query_Sum(x , y)) ;
        }
        if(opt == 3) {
            int x = read() , y = read() ;
            x ++ , y ++ ;
            write(Query_Max(x , y)) ;
        }
        if(opt == 4) {
            int x = read() , y = read() ;
            x ++ , y  ++ ;
            write(Query_Min(x , y)) ;
        }
    }
    return 0 ;
}
相關文章
相關標籤/搜索