LuoguP1505 [国家集训队]旅游 (树链剖分)

边权下放到点权,因为一父一子(树的计划生育)。区间取反就是\(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;
} 

猜你喜欢

转载自www.cnblogs.com/bingoyes/p/11705770.html
今日推荐