Dynamic split tree bzoj3589 chain inclusion and exclusion +

Topic Portal

https://lydsy.com/JudgeOnline/problem.php?id=3589

answer

Event \ (0 \) do not need to say directly to do it.

Event \ (1 \) , then consider if the direct query then added, there will be a lot of segments are considered heavy. So consider inclusion and exclusion, the weight calculation section to lose it. As for how to calculate each piece of the answer, direct tree cross bar.


Time complexity \ (O (^. 5 Q \ ^ log 2N) \) .

#include<bits/stdc++.h>

#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back

template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;}

typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;

template<typename I> inline void read(I &x) {
    int f = 0, c;
    while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
    x = c & 15;
    while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
    f ? x = -x : 0;
}

#define lc o << 1
#define rc o << 1 | 1
#define lowbit(x) ((x) & -(x))

const int N = 200000 + 7;

int n, m, k, dfc;
int dep[N], f[N], siz[N], son[N], dfn[N], pre[N], top[N];
int qx[40], qy[40], pcnt[40];

struct Edge { int to, ne; } g[N << 1]; int head[N], tot;
inline void addedge(int x, int y) { g[++tot].to = y, g[tot].ne = head[x], head[x] = tot; }
inline void adde(int x, int y) { addedge(x, y), addedge(y, x); }

struct Node { int add, sum; } t[N << 2];
inline void qadd(int o, int L, int R, int l, int r, int k) {
    if (l <= L && R <= r) return t[o].add += k, t[o].sum += (R - L + 1) * k, (void)0;
    int M = (L + R) >> 1;
    if (l <= M) qadd(lc, L, M, l, r, k);
    if (r > M) qadd(rc, M + 1, R, l, r, k);
    t[o].sum = t[lc].sum + t[rc].sum + t[o].add * (R - L + 1);
}
inline int qsum(int o, int L, int R, int l, int r, int add = 0) {
    if (l <= L && R <= r) return t[o].sum + add * (R - L + 1);
    int M = (L + R) >> 1;
    if (r <= M) return qsum(lc, L, M, l, r, add + t[o].add);
    if (l > M) return qsum(rc, M + 1, R, l, r, add + t[o].add);
    return qsum(lc, L, M, l, r, add + t[o].add) + qsum(rc, M + 1, R, l, r, add + t[o].add);
}

inline void upd(int x, int k) { qadd(1, 1, n, dfn[x], dfn[x] + siz[x] - 1, k); }
inline int qry(int x, int y) {
    int ans = 0;
    while (top[x] != top[y]) {
        if (dep[top[x]] < dep[top[y]]) std::swap(x, y);
        ans += qsum(1, 1, n, dfn[top[x]], dfn[x]);
        x = f[top[x]];
    }
    if (dep[x] > dep[y]) std::swap(x, y);
    return ans += qsum(1, 1, n, dfn[x], dfn[y]);
}

inline void dfs1(int x, int fa = 0) {
    dep[x] = dep[fa] + 1, f[x] = fa, siz[x] = 1;
    for fec(i, x, y) if (y != fa) dfs1(y, x), siz[x] += siz[y], siz[y] > siz[son[x]] && (son[x] = y);
}
inline void dfs2(int x, int pa) {
    top[x] = pa, dfn[x] = ++dfc, pre[dfc] = x;
    if (!son[x]) return; dfs2(son[x], pa);
    for fec(i, x, y) if (y != f[x] && y != son[x]) dfs2(y, y);
}
inline int lca(int x, int y) {
    while (top[x] != top[y]) dep[top[x]] >= dep[top[y]] ? x = f[top[x]] : y = f[top[y]];
    return dep[x] < dep[y] ? x : y;
}

inline bool intree(int x, int y) { return dfn[y] >= dfn[x] && dfn[y] <= dfn[x] + siz[x] - 1; }
inline pii merge(pii l1, pii l2) {
    if (dep[l1.fi] > dep[l1.se]) std::swap(l1.fi, l1.se);
    if (dep[l2.fi] > dep[l2.se]) std::swap(l2.fi, l2.se);
    if (dep[l1.fi] > dep[l2.fi]) std::swap(l1, l2);
    if (intree(l1.fi, l2.fi) && intree(l2.fi, l1.se)) return pii(l2.fi, lca(l1.se, l2.se));
    else return pii(0, 0);
}

inline void work() {
    dfs1(1), dfs2(1, 1);
    read(m);
    while (m--) {
        int opt, x, y;
        read(opt);
        if (opt == 0) read(x), read(y), upd(x, y);
        else {
            read(k);
            for (int i = 1; i <= k; ++i) read(qx[1 << (i - 1)]), read(qy[1 << (i - 1)]);
            int ans = 0, S = (1 << k) - 1;
            for (int s = 1; s <= S; ++s) {
                int sta = s ^ lowbit(s);
                pcnt[s] = pcnt[sta] + 1;
                if (sta) {
                    pii hkk = merge(pii(qx[lowbit(s)], qy[lowbit(s)]), pii(qx[sta], qy[sta]));
                    qx[s] = hkk.fi, qy[s] = hkk.se;
                }
                if (qx[s]) {
                    if (pcnt[s] & 1) ans += qry(qx[s], qy[s]);
                    else ans -= qry(qx[s], qy[s]);
                }
            }
            printf("%d\n", ans & ((1 << 31) - 1));
        }
    }
}

inline void init() {
    read(n);
    int x, y;
    for (int i = 1; i < n; ++i) read(x), read(y), adde(x, y);
}

int main() {
#ifdef hzhkk
    freopen("hkk.in", "r", stdin);
#endif
    init();
    work();
    fclose(stdin), fclose(stdout);
    return 0;
}

Guess you like

Origin www.cnblogs.com/hankeke/p/bzoj2589.html