BZOJ 2157 Tourism (tree chain split)

Topic link: https: //www.lydsy.com/JudgeOnline/problem.php id = 2157?

This question is given in the right side, so we want to convert to the right point.

Topic requires the operator:

1. Query resort sum u, all the bridges between the pleasure values ​​v

2. Query the maximum scenic u, v pleasant value bridge between

3. Query scenic minimum u, v pleasant value bridge between

4. The scenic u, v pleasure value between all bridges -1

The value of the joy i bridge modified to C

Thinking: Because only one path between any two points in the city, then the city may be regarded as a tree, you may be required for operation above a chain split tree.

detail:

1. update down, left and right children's lazy labeling XOR 1, rather than directly assign 1

2. interval value -1, the maintenance suml inverted, after inverted maxl, minl can exchange

3. The so-called bridges, i.e. we adjacency table storage side, from where we start storing the subscript 2 side, since the memory is undirected edges, so we only need to bridge number i << 1, i << 1 | 1 that is obtained is the index of the adjacent table edge

(E.g., first bridge certainly edge [2], edge [3]), and we can find the point corresponding to each bridge (compare dep and two sides, the weight of this part of the bridge than the depth large dots), so that we successfully convert the right side to the right point

4. scenic u, v during operation between, when two points u, v jump with a heavy chain, the smaller weight value of the depth point should not be considered, because the operation is the u, v between right side, while the right depth definitely not a small point u, v between

#include <cmath>
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <ctype.h>
#include <map>
#include <vector>
#include <set>
#include <bitset>
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define L(rt) rt << 1
#define R(rt) rt << 1 | 1
#define INF 0x7fffffff
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
static const int MAX_N = 1e5 + 5;
static const int Mod = 10007;
struct Edge {
    int to, w, next;
}edge[MAX_N << 1];
int head[MAX_N];    //链式前向星
int a[MAX_N];
int siz[MAX_N], son[MAX_N], top[MAX_N], fa[MAX_N], id[MAX_N], dep[MAX_N], rk[MAX_N];
int cnt, tot;
void dfs1(int u, int f, intD) {      // first son of a weight dfs 
    SIZ [U] = . 1 ; 
    Son [U] = 0 ; 
    FA [U] = F; 
    DEP [U] = D;
     for ( int I = head [U]; I; I = Edge [I] .next) {
         int V = Edge [I] .to;
         IF (V == F) Continue ;     // do not take repeated passage 
        A [V] = Edge [I] .W; 
        DFS1 (V, U, D + . 1 ); 
        SIZ [U] + = SIZ [V];
         IF (SIZ [V]> SIZ [Son [U]]) Son [U] =V; 
    } 
} 
void DFS2 ( int U, int T) {      // the son ligation into a heavy chain, light son connected light chain (obtained interval) 
    Top [U] = T; 
    ID [U] = ++ CNT; 
    RK [CNT] = U;
     IF (Son [U]) DFS2 (Son [U], T);   // priority of the heavy chain 
    for ( int I = head [U]; I; I = Edge [I] .next ) {
         int V = Edge [I] .to;
         IF !! (V Son = [U] && V = FA [U]) DFS2 (V, V); 
    } 
} 
int getPoint ( int U) { return dep[edge[u << 1].to] > dep[edge[u << 1 | 1].to] ? edge[u << 1].to : edge[u << 1 | 1].to; }
struct Node {
    int l, r;
    int minl, maxl, suml, tag;
}T[MAX_N << 2];
void prework() {
    memset(head, 0, sizeof(head));
    cnt = 0;
    tot = 1;
}
void addEdge(int u, int v, int w) {
    edge[++tot].to = v;
    edge[tot].next = head[u];
    edge[tot].w = w;
    head[u] = tot;
}
void pushUp(int rt) {
    T[rt].suml = T[L(rt)].suml + T[R(rt)].suml;
    T[rt].maxl = max(T[L(rt)].maxl, T[R(rt)].maxl);
    T[rt].minl = min(T[L(rt)].minl, T[R(rt)].minl);
}
void build(int rt, int l, int r) {
    T[rt].l = l;
    T[rt].r = r;
    T[rt].tag = 0;
    if (l == r) {
        T[rt].maxl = T[rt].minl = T[rt].suml = a[rk[l]];
        return;
    }
    int mid = l + r >> 1;
    build(lson);
    build(rson);
    pushUp(rt);
}
void pushNow(int rt) {
    swap(T[rt].maxl, T[rt].minl);
    T[rt].maxl = -T[rt].maxl;
    T[rt].minl = -T[rt].minl;
    T[rt].suml = -T[rt].suml;
    T[rt].tag ^= 1;
}
void pushDown(int rt) {
    if (T[rt].tag) {
        pushNow(L(rt));
        pushNow(R(rt));
        T[rt].tag = 0;
    }
}
void updatePoint(int rt, int pos, int c) {
    if (T[rt].l == T[rt].r) {
        T[rt].maxl = T[rt].minl = T[rt].suml = c;
        return;
    }
    pushDown(rt);
    int mid = T[rt].l + T[rt].r >> 1;
    if (pos <= mid) updatePoint(L(rt), pos, c);
    else updatePoint(R(rt), pos, c);
    pushUp(rt);
}
void updateInterval(int rt, int ql, int qr) {
    if (T[rt].l > qr || T[rt].r < ql) return;
    if (T[rt].l >= ql && T[rt].r <= qr) {
        pushNow(rt);
        return;
    }
    pushDown(rt);
    int mid = T[rt].l + T[rt].r >> 1;
    if (ql <= mid) updateInterval(L(rt), ql, qr);
    if (qr > mid) updateInterval(R(rt), ql, qr);
    pushUp(rt);
}
int queryMax(int rt, int ql, int qr) {
    if (T[rt].l > qr || T[rt].r < ql) return -INF;
    if (T[rt].l >= ql && T[rt].r <= qr) return T[rt].maxl;
    pushDown(rt);
    int ans = -INF;
    int mid = T[rt].l + T[rt].r >> 1;
    if (ql <= mid) ans = max(ans, queryMax(L(rt), ql, qr));
    if (qr > mid) ans = max(ans, queryMax(R(rt), ql, qr));
    return ans;
}
int querySum(int rt, int ql, int qr) {
    if (T[rt].l > qr || T[rt].r < ql) return 0;
    if (T[rt].l >= ql && T[rt].r <= qr) return T[rt].suml;
    pushDown(rt);
    int mid = T[rt].l + T[rt].r >> 1;
    int ans = 0;
    if (ql <= mid) ans += querySum(L(rt), ql, qr);
    if (qr > mid) ans +=  querySum(R(rt), ql, qr);
    return ans;
}
int queryMin(int rt, int ql, int qr) {
    if (T[rt].l > qr || T[rt].r < ql) return INF;
    if (T[rt].l >= ql && T[rt].r <= qr) return T[rt].minl;
    pushDown(rt);
    int ans = INF;
    int mid = T[rt].l + T[rt].r >> 1;
    if (ql <= mid) ans = min(ans, queryMin(L(rt), ql, qr));
    if (qr > mid) ans = min(ans, queryMin(R(rt), ql, qr));
    return ans;
}
void updatePathVal(int u, int v) {
    while (top[u] != top[v]) {
        if (dep[top[u]] < dep[top[v]]) swap(u, v);
        updateInterval(1, id[top[u]], id[u]);
        u = fa[top[u]];
    }
    if (dep[u] > dep[v]) swap(u, v);
    updateInterval(1, id[u] + 1, id[v]);
}
int queryPathMax(int u, int v) {
    int ans = -INF;
    while (top[u] != top[v]) {
        if (dep[top[u]] < dep[top[v]]) swap(u, v);
        ans = max(ans, queryMax(1, id[top[u]], id[u]));
        u = fa[top[u]];
    }
    if (dep[u] > dep[v]) swap(u, v);
    ans = max(ans, queryMax(1, id[u] + 1, id[v]));
    return ans;
}
int queryPathSum(int u, int v) {
    int ans = 0;
    while (top[u] != top[v]) {
        if (dep[top[u]] < dep[top[v]]) swap(u, v);
        ans += querySum(1, id[top[u]], id[u]);
        u = fa[top[u]];
    }
    if (dep[u] > dep[v]) swap(u, v);
    ans += querySum(1, id[u] + 1, id[v]);
    return ans;
}
int queryPathMin(int u, int v) {
    int ans = INF;
    while (top[u] != top[v]) {
        if (dep[top[u]] < dep[top[v]]) swap(u, v);
        ans = min(ans, queryMin(1, id[top[u]], id[u]));
        u = fa[top[u]];
    }
    if (dep[u] > dep[v]) swap(u, v);
    ans = min(ans, queryMin(1, id[u] + 1, id[v]));
    return ans;
}
void mainwork(){
    /*freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);*/
    int n, q;
    scanf("%d", &n);
    for (int i = 1; i < n; ++i) {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        ++u,++ v;
        addEdge(u, v, w);
        addEdge(v, u, w);
    }
    dfs1(1, 1, 1);
    dfs2(1, 1);
    build(1, 1, n);
    scanf("%d", &q);
    while (q--) {
        char opt[5];
        int u, v, c;
        scanf("%s%d%d", opt, &u, &v);
        if (opt[0] == 'C') updatePoint(1, id[getPoint(u)], v);
        else if (opt[0] == 'N') updatePathVal(u + 1, v + 1);
        else if (opt[1] == 'U') printf("%d\n", queryPathSum(u + 1, v + 1));
        else if (opt[1] == 'I') printf("%d\n", queryPathMin(u + 1, v + 1));
        else  printf("%d\n", queryPathMax(u + 1, v + 1));
    }
}
int main() {
    prework();
    mainwork();
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/xorxor/p/11270092.html