"Luogu P3313" [SDOI2014] travel

\ (S \) state-owned \ (N \) cities, numbered from \ (1 \) to \ (N \) . Between city use \ (N - 1 \) two-way road connections, meet a city can be reached from all other cities. Different religious beliefs of each city, such as flying noodles polytheism, invisible unicorn teach, Jedi are common beliefs.

For convenience, we use a variety of distinct positive integers religious representatives, residents often travel S State. When traveling they always take the shortest path, and in order to avoid trouble, only in the same faith and the city they live. Of course, also the end of the journey of faith with his same city. S Government calibrated different travel rating for each city, travelers often write down the way (including start and end) rating or the sum of the maximum stay off the city.

Often several of the following events occur in the history of S country:

CC x c: City \ (x \) residents of all converted to a \ (c \) to teach;

CW x w: City \ (x \) rating adjusted to \ (w \) ;

QS x y: A traveler from the city \ (x \) departure, the city \ (the y-\) , and recorded the sum of the way through the city overnight rating;

QM x y: A traveler from the city \ (x \) departure, the city \ (the y-\) , and recorded the maximum rating of the way through the city overnight.

Because of the age, digital note of travelers have been lost, but recorded before the start of each city beliefs and ratings, as well as event logging itself is intact. Make this information, the reduction in the numbers traveler in mind. For convenience, we consider the interval between events long enough so that at any one trip, all of the city's ratings and beliefs remain unchanged.

Luogu

analysis

If there is no religious property, so this question is a bare tree chain split, but with it, how to do? Each religion to build a tree line? Space is certainly explode. So we can refer to the idea of ​​the President of trees, dynamic opening point, and then update it corresponds to the religious segment tree with each node, and modify the operation, if it is modified religion, we also need to delete the operation, the other is normal operation.

Some gossip. Spicy chicken \ (strcmp \) , causing me to MLE countless hair.

Code

#include <bits/stdc++.h>

#define N 100003
#define rg register

using namespace std;

int gi() {
    rg int x = 0, f = 1; rg char c = getchar();
    for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
    for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    return x * f;
}

void chkmax(int &x, int y) { if (x < y) x = y; }

struct SegmentTree {
    int ls, rs, sum, mx;
} t[N << 5];

int n, q, tot, num;
int w[N], c[N], rt[N];
int to[N << 1], nxt[N << 1], hd[N], cnt;
int dep[N], fa[N], dfn[N], rk[N], sz[N], son[N], top[N];

void insert(int u, int v) { to[++cnt] = v, nxt[cnt] = hd[u], hd[u] = cnt; }

void dfs1(int u, int f) {
    dep[u] = dep[f] + 1, fa[u] = f, sz[u] = 1;
    for (int i = hd[u]; i; i = nxt[i]) {
        int v = to[i];
        if (v == f) continue;
        dfs1(v, u);
        sz[u] += sz[v];
        if (sz[v] > sz[son[u]]) son[u] = v;
    }
}

void dfs2(int u, int tp) {
    dfn[u] = ++tot, rk[tot] = u, top[u] = tp;
    if (son[u]) dfs2(son[u], tp);
    for (int i = hd[u]; i; i = nxt[i]) {
        if (to[i] != fa[u] && to[i] != son[u])
            dfs2(to[i], to[i]);
    }
}

void pushup(int o) {
    t[o].sum = t[t[o].ls].sum + t[t[o].rs].sum;
    t[o].mx = max(t[t[o].ls].mx, t[t[o].rs].mx);
}

void modify(int &o, int l, int r, int p) {
    if (!o) o = ++num;
    if (l == r) {
        t[o].sum = t[o].mx = w[rk[p]];
        return;
    }
    int mid = l + r >> 1;
    if (p <= mid) modify(t[o].ls, l, mid, p);
    else modify(t[o].rs, mid + 1, r, p);
    pushup(o);
}

void del(int o, int l, int r, int p) {
    if (l == r) {
        t[o].sum = t[o].mx = 0;
        return;
    }
    int mid = l + r >> 1;
    if (p <= mid) del(t[o].ls, l, mid, p);
    else del(t[o].rs, mid + 1, r, p);
    pushup(o);
}

int QuerySum(int o, int l, int r, int ql, int qr) {
    if (l >= ql && r <= qr) return t[o].sum;
    int mid = l + r >> 1, ret = 0;
    if (ql <= mid) ret += QuerySum(t[o].ls, l, mid, ql, qr);
    if (qr > mid) ret += QuerySum(t[o].rs, mid + 1, r, ql, qr);
    return ret;
}

int QueryMax(int o, int l, int r, int ql, int qr) {
    if (l >= ql && r <= qr) return t[o].mx;
    int mid = l + r >> 1, ret = 0;
    if (ql <= mid) chkmax(ret, QueryMax(t[o].ls, l, mid, ql, qr));
    if (qr > mid) chkmax(ret, QueryMax(t[o].rs, mid + 1, r, ql, qr));
    return ret;
}

int GetSum(int x, int y) {
    int tx = top[x], ty = top[y], ret = 0, cx = c[x], cy = c[y];
    while (tx != ty) {
        if (dep[tx] >= dep[ty])
            ret += QuerySum(rt[cx], 1, n, dfn[tx], dfn[x]), x = fa[tx];
        else
            ret += QuerySum(rt[cy], 1, n, dfn[ty], dfn[y]), y = fa[ty];
        tx = top[x], ty = top[y];
    }
    if (dfn[x] < dfn[y]) ret += QuerySum(rt[cx], 1, n, dfn[x], dfn[y]);
    else ret += QuerySum(rt[cx], 1, n, dfn[y], dfn[x]);
    return ret;
}

int GetMax(int x, int y) {
    int tx = top[x], ty = top[y], ret = 0, cx = c[x], cy = c[y];
    while (tx != ty) {
        if (dep[tx] >= dep[ty])
            chkmax(ret, QueryMax(rt[cx], 1, n, dfn[tx], dfn[x])), x = fa[tx];
        else
            chkmax(ret, QueryMax(rt[cy], 1, n, dfn[ty], dfn[y])), y = fa[ty];
        tx = top[x], ty = top[y];
    }
    if (dfn[x] < dfn[y]) chkmax(ret, QueryMax(rt[cx], 1, n, dfn[x], dfn[y]));
    else chkmax(ret, QueryMax(rt[cx], 1, n, dfn[y], dfn[x]));
    return ret;
}

int main() {
    int u, v;
    char op[5];
    n = gi(), q = gi();
    for (int i = 1; i <= n; ++i) w[i] = gi(), c[i] = gi();
    for (int i = 1; i < n; ++i) {
        u = gi(), v = gi();
        insert(u, v), insert(v, u);
    }
    dfs1(1, 0), dfs2(1, 1);
    for (int i = 1; i <= n; ++i) modify(rt[c[rk[i]]], 1, n, i);
    for (int i = 1; i <= q; ++i) {
        scanf("%s", op);
        u = gi(), v = gi();
        if (op[1] == 'C') {
            del(rt[c[u]], 1, n, dfn[u]);
            c[u] = v;
            modify(rt[v], 1, n, dfn[u]);
        }
        else if (op[1] == 'W') {
            w[u] = v;
            modify(rt[c[u]], 1, n, dfn[u]);
        }
        else if (op[1] == 'S') printf("%d\n", GetSum(u, v));
        else printf("%d\n", GetMax(u, v));
    }
    return 0;
}

The following is because I \ (strcmp \) MLE and caused problems facing the space occupied by the solution changed less often add a point card code

Code

Code on the wind LOJ really nice

Guess you like

Origin www.cnblogs.com/hlw1/p/12288614.html