[Luo Gu P4315] next month, "Jing Mao" tree

Topic links:

click me

Topic analysis:

Tree section. The right side into the next point on the bottom (why should I vote deeper point? May correspond to more than a father his son, but a son only a father, namely to ensure that each point can only save one edge right) became a classic right point + tree bare sectional title
Note chain can not enumerated LCA calculations, the remaining more details, see the specific code.

Code:

#include<bits/stdc++.h>
#define N (100000 + 5)
#define inf (1000000000+7)
using namespace std;
inline int read() {
    int cnt = 0, f = 1; char c;
    c = getchar();
    while(!isdigit(c)) {
        if (c == '-') f = -f;
        c = getchar(); 
    }
    while(isdigit(c)) {
        cnt = cnt * 10 + c - '0';
        c = getchar();
    }
    return cnt * f;
}
int nxt[N * 2], first[N * 2], to[N * 2], w[N * 2], a[N], tot;
int father[N], top[N], siz[N], dep[N], son[N], num[N], id[N], idx;
int n, u, v, W, k;
char opr[20];
struct node{
    int l, r;
    long long cov, add, gmax;
    #define l(p) tree[p].l
    #define r(p) tree[p].r
    #define cov(p) tree[p].cov
    #define add(p) tree[p].add
    #define gmax(p) tree[p].gmax
} tree[N * 4];

struct edge{
    int u; int v;
}e[N * 2];

void Add(int x, int y, int z) {
    nxt[++tot] = first[x];
    first[x] = tot;
    to[tot] = y;
    w[tot] = z;
}

void dfs1(int cur, int fa) {
    father[cur] = fa; siz[cur] = 1; dep[cur] = dep[fa] + 1;
    for (register int i = first[cur]; i; i = nxt[i]) {
        int v = to[i];
        if(v != fa) {
            a[v] = w[i];
            dfs1(v, cur);
            siz[cur] += siz[v];
            if(siz[son[cur]] < siz[v]) son[cur] = v;
        }
    }
}

void dfs2(int cur, int tp) {
    top[cur] = tp; num[cur] = ++idx; id[idx] = cur;
    if (son[cur]) dfs2(son[cur], tp);
    for (register int i = first[cur]; i; i = nxt[i]) {
        int v = to[i];
        if (!num[v]) dfs2(v, v);
    }
}

void pushup(int p) {
    gmax(p) = max(gmax(p << 1), gmax(p << 1 | 1));
}
void pushcover(int p, int v){cov(p) = v; add(p) = 0; gmax(p) = v;}
void pushadd(int p,int v){ add(p)+=v; gmax(p)+=v;}
void pushdown(int p) {
    if (cov(p) >= 0) {
        pushcover(p<<1, cov(p)); pushcover(p<<1|1, cov(p)); cov(p) = -1; 
    }
    if (add(p)) {
        pushadd(p<<1, add(p)); pushadd(p<<1|1, add(p)); add(p) = 0; 
    }
}

void build_tree(int p, int l, int r) {
    l(p) = l; r(p) = r; cov(p) = -1;
    if(l == r) {
        gmax(p) = a[id[l]];
    //  cout<<l<<" "<<r<<" "<<gmax(p)<<endl;
        return;
    }
    int mid = (l + r) >> 1;
    build_tree(p << 1, l, mid);
    build_tree(p << 1 | 1, mid + 1, r);
    pushup(p);
}
void debug(int u,int l,int r){
    if(l==r){
        cout<<id[l]<<" "<<gmax(u)<<endl;return;
    }int mid=(l+r)>>1;
    debug(u*2,l,mid);debug(u*2+1,mid+1,r);
}
void Cover(int p, int l, int r, int d) {
    if (l > r) return;
    if (l <= l(p) && r >= r(p)) {
        pushcover(p, d);
        return;
    }
    pushdown(p);
    int mid = (l(p) + r(p)) >> 1;
    if (l <= mid) Cover(p << 1, l, r, d);
    if (r > mid) Cover(p << 1 | 1, l, r, d);
    pushup(p);
}

void Modify(int p, int l, int r, int d) {
    if (l > r) return;
    if (l <= l(p) && r >= r(p)) {
//      if(cov(p) >= 0) {
//          cov(p) += d;
//          gmax(p) += d;
//      } else {
//          pushadd(p, d);
//      }
        pushadd(p, d);
        return;
    }
    pushdown(p);
    int mid = (l(p) + r(p)) >> 1; 
    if (l <= mid) Modify(p << 1, l, r, d);
    if (r > mid) Modify(p << 1 | 1, l, r, d);
    pushup(p);
}

long long query(int p, int l, int r) {
//  cout<<p<<" "<<l(p)<<" "<<r(p)<<endl; 
    if (l <= l(p) && r >= r(p)) return gmax(p);
    int mid = (l(p) + r(p)) >> 1;
    pushdown(p);
    //cout<<p<<endl;
    long long val = -inf;
    if (l <= mid) val = max (val, query(p << 1, l, r));
    if (r > mid) val = max(val, query(p << 1 | 1, l, r));
    return val;
}

void chain_cover(int u, int v, int d) {
    while (top[u] != top[v]) {
        if (dep[top[u]] < dep[top[v]]) swap(u, v);
        Cover(1, num[top[u]], num[u], d);
        u = father[top[u]];
    }
    if (dep[u] < dep[v]) swap(u, v);
//  if (u == v) Cover(1, num[v], num[u], d);
    Cover(1, num[v] + 1, num[u], d);
}

void chain_modify(int u, int v, int d) {
    while (top[u] != top[v]) {
        if (dep[top[u]] < dep[top[v]]) swap(u, v);
        Modify(1, num[top[u]], num[u], d);
        u = father[top[u]];
    }
    if (dep[u] < dep[v]) swap(u, v);
//  if (u == v) Modify(1, num[v], num[u], d);
    Modify(1, num[v] + 1, num[u], d);
}

long long chain_query(int u, int v) { 
    long long ans = -inf;
    while (top[u] != top[v]) {//cout<<u<<endl;
    //  cout<<top[u]<<" "<<top[v]<<endl;
        if (dep[top[u]] < dep[top[v]]) swap(u, v);
    //  cout<<top[u]<<" "<<top[v]<<endl;
    //  cout<<num[top[u]]<<" "<<num[u]<<endl;
    //  cout<<query(1,num[top[u]],num[u])<<"###"<<endl;
        ans = max(ans, query(1, num[top[u]], num[u]));//cout<<"#";
        u = father[top[u]];
    //  cout<<ans<<endl;
    }
    if (dep[u] < dep[v]) swap(u, v);
    ans = max(ans, query(1, num[v] + 1, num[u]));
    return ans;
}

void solve() {
    n = read();
    for (register int i = 1; i < n; i++) {
        u = read(); v = read(); W = read();
        e[i].u = u; e[i].v = v;
        Add(u, v, W); Add(v, u, W);
    }
    dfs1(1, 0); dfs2(1, 1);
//  for(int i=1;i<=n;i++)cout<<a[i]<<" ";cout<<endl;
//  for(int i=1;i<=n;i++)cout<<id[i]<<" ";cout<<endl;
    build_tree(1, 1, n);
//  debug(1,1,n);
//  cout<<"#"<<endl;
    for (;;) {
        scanf("%s", opr + 1);
        if (opr[1] == 'M') {
            u = read(); v = read(); 
            printf("%lld\n", chain_query(u, v));
        }
        if (opr[1] == 'C') {
            if (opr[2] == 'o') {
                u = read(); v = read(); W = read();
                chain_cover(u, v, W);
            }
            if (opr[2] == 'h') {
                u = read(); W = read();
                if (dep[e[u].u] < dep[e[u].v]) swap(e[u].u, e[u].v);
//              cout<<"nmsl"<<e[u].u<<" "<<e[u].v<<endl;
//              cout<<"##"<<num[e[u].u]<<"WWW"<<W<<endl;
//              chain_cover(num[e[u].u], num[e[u].v], W);
                Cover(1, num[e[u].u], num[e[u].u], W);
            }
        }
        if (opr[1] == 'A') {
            u = read(); v = read(); W = read();
            chain_modify(u, v, W);
        }
        if (opr[1] == 'S') break;
//      debug(1,1,n);cout<<endl;
    }
    return;
}

int main() {
//  freopen("input.in","r",stdin);
    solve();
    return 0;
}

Guess you like

Origin www.cnblogs.com/kma093/p/11059141.html