[CF1192B]Dynamic Diameter

题目

传送门

题解

题目交代了是“动态直径”,肯定是在线啦,问题在于我们选用什么数据结构维护,以及怎么维护.

比较经典地,对于每个数标上 \(\tt dfn\),然后使用线段树维护。问题是在线段树上如何维护一个区间的点的直径?对于一颗线段树上的区间,它的直径的两个端点必然来源于它的子区间的两条直径的端点,我们只需要用四次枚举每种情况即可.

考虑修改的时候怎么维护线段树,首先,对于一条边 \(e\) 被修改,假设它连接的深度较深的点为 \(u\),那么,在 \(u\) 的子树中的直径没有受到影响,唯一有影响的是跨越\(u\) 的点的直径,在线段树上来说,就是包含了 dfn[u] 以及 dfn[u]+sz[u]-1 两个端点的区间需要重新计算,一次修改的计算是 \(\mathcal O(\log^2n)\),总复杂度 \(\mathcal O(n\log^2n)\).

代码中对于单点的深度使用的是 BIT 利用差分维护的.

代码

# include <cstdio>
# include <algorithm>
using namespace std;
namespace Elaina{
    # define rep(i,l,r) for(int i=l, i##_end_ = r; i <= i##_end_; ++ i)
    # define fep(i,l,r) for(int i=l, i##_end_ = r; i >= i##_end_; -- i)
    # define fi first
    # define se second
    # define Endl putchar('\n')
    # define writc(x, c) fwrit(x), putchar(c)
    // # define int long long
    typedef long long ll;
    typedef pair<int, int> pii;
    typedef unsigned long long ull;
    typedef unsigned int uint;
    template<class T>inline T Max(const T x, const T y){return x < y ? y : x;}
    template<class T>inline T Min(const T x, const T y){return x < y ? x : y;}
    template<class T>inline T fab(const T x){return x < 0 ? -x : x;}
    template<class T>inline void getMax(T& x, const T y){x = Max(x, y);}
    template<class T>inline void getMin(T& x, const T y){x = Min(x, y);}
    template<class T>T gcd(const T x, const T y){return y ? gcd(y, x % y) : x;}
    template<class T>inline T readin(T x){
        x=0; int f = 0; char c;
        while((c = getchar()) < '0' || '9' < c) if(c == '-') f = 1;
        for(x = (c ^ 48); '0' <= (c = getchar()) && c <= '9'; x = (x << 1) + (x << 3) + (c ^ 48));
        return f ? -x : x;
    }
    template<class T>void fwrit(const T x){
        if(x < 0)return putchar('-'), fwrit(-x);
        if(x > 9)fwrit(x / 10); putchar(x % 10 ^ 48);
    }
}
using namespace Elaina;

const int maxn = 1e5;
const ll inf = (1ll << 50);

int n, q; ll w;

struct edge{int to, nxt; ll w;
    edge(const int T = 0, const int N = 0, const ll W = 0) : to(T), nxt(N), w(W){}
}e[maxn * 2 + 5];
int ecnt = 1;// pay attention!
int tail[maxn + 5];
inline void add_edge(const int u, const int v, const ll w){
    e[++ ecnt] = edge(v, tail[u], w); tail[u] = ecnt;
    e[++ ecnt] = edge(u, tail[v], w); tail[v] = ecnt;
}

inline void init(){
    n = readin(1), q = readin(1); w = readin(1ll);
    int a, b; ll c;
    rep(i, 1, n - 1){
        a = readin(1), b = readin(1), c = readin(1ll);
        add_edge(a, b, c);
    }
}

ll dis[maxn + 5];
int sz[maxn + 5], wson[maxn + 5], dep[maxn + 5], fa[maxn + 5];
void dfs1(const int u, const int par){
    sz[u] = 1, dep[u] = dep[par] + 1, fa[u] = par;
    for(int i = tail[u], v; i; i = e[i].nxt)
        if((v = e[i].to) != par){
        dis[v] = dis[u] + e[i].w;
        dfs1(v, u), sz[u] += sz[v];
        if(sz[v] > sz[wson[u]]) wson[u] = v;
    }
}
int c[maxn + 5], dfn[maxn + 5], tp[maxn + 5], times;
void dfs2(const int u, const int par){
    c[dfn[u] = ++ times] = u;
    if(!wson[u]) return;
    tp[wson[u]] = tp[u], dfs2(wson[u], u);
    for(int i = tail[u], v; i; i = e[i].nxt)
        if((v = e[i].to) != par && v != wson[u])
            dfs2(tp[v] = v, u);
}

inline int findlca(int u, int v){
    while(tp[u] != tp[v]){
        // printf("Now u == %d, v == %d\n", u, v);
        if(dep[tp[u]] < dep[tp[v]]) swap(u, v);
        u = fa[tp[u]];
    }
    return dep[u] < dep[v] ? u : v;
}

inline int lowbit(const int i){return i & (-i);}
/** @brief maintain the distance of the nodes*/
struct BIT{
    ll c[maxn + 5];
    inline void modify(int i, const ll x){
        for(; i <= n; i += lowbit(i))
            c[i] += x;
    }
    inline void modify(const int l, const int r, const ll x){
        modify(l, x), modify(r + 1, -x);
    }
    inline ll query(int i){
        ll ret = 0;
        for(; i > 0; i -= lowbit(i)) ret += c[i];
        return ret;
    }
}bit;

inline ll query_dis(const int u, const int v){
    // printf("query_dis :> u == %d, v == %d\n", u, v);
    if(u == 0 || v == 0) return -inf;
    int lca = findlca(u, v);
    return bit.query(dfn[u]) + bit.query(dfn[v]) - 2 * bit.query(dfn[lca]);
}

struct diameter{
    int c[2]; ll d;
    inline diameter operator &(const diameter rhs) const{
        diameter ret;
        if(d < rhs.d) ret = rhs;
        else ret = (*this);
        rep(i, 0, 1) rep(j, 0, 1){
            int x = c[i], y = rhs.c[j];
            ll dis;
            if((dis = query_dis(x, y)) > ret.d){
                ret.d = dis;
                ret.c[0] = x, ret.c[1] = y;
            }
        }
        return ret;
    }
};

/** @brief maintain the particular interval's diameter*/
diameter tre[maxn << 2 | 2];
# define ls (i << 1)
# define rs (i << 1 | 1)
# define mid ((l + r) >> 1)
# define _lq ls, l, mid
# define _rq rs, mid + 1, r
inline void pushup(const int i){
    tre[i] = tre[ls] & tre[rs];
}
void Build(const int i = 1, const int l = 1, const int r = n){
    if(l == r){
        tre[i].c[0] = c[l];
        tre[i].d = -inf;
        return;
    }
    Build(_lq), Build(_rq);
    pushup(i);
}
void Modify(const int L, const int R, const int i = 1, const int l = 1, const int r = n){
    if(L <= l && r <= R) return;
    if(L <= mid) Modify(L, R, _lq);
    if(mid < R) Modify(L, R, _rq);
    pushup(i);
}
void print(const int i = 1, const int l = 1, const int r = n){
    if(l != r) print(_lq), print(_rq);
    printf("tre[%d] :> l == %d, r == %d, (%d, %d, %lld)\n", i, l, r, tre[i].c[0], tre[i].c[1], tre[i].d);
}

signed main(){
    init();
    dfs1(1, 0);
    // puts("finished 1!");
    dfs2(tp[1] = 1, 0);
    // puts("finished 2!");
    rep(i, 1, n){
        // 注意此处传的下标
        bit.modify(i, dis[c[i]] - dis[c[i - 1]]);
        // printf("bit[%d].insert %lld\n", i, dis[c[dfn[i]]] - dis[c[dfn[i - 1]]]);
    }
    // puts("finished 3!");
    // rep(i, 1, n){
    //     printf("node %d :> sz == %d, wson == %d, fa == %d, dep == %d, dis == %lld, tp == %d, dfn == %d\n", i, sz[i], wson[i], fa[i], dep[i], dis[i], tp[i], dfn[i]);
    // }
    // rep(i, 1, n) printf("dis %d == %lld\n", i, bit.query(dfn[i]));

    Build();
    // printf("ans 1 == %lld\n", tre[1].d);
    // print();
    // rep(i, 1, n) printf("dis %d == %lld\n", i, bit.query(i));
    ll las = 0, E; int D;
    while(q --){
        D = (0ll + readin(1) + las) % (n - 1) + 1;
        E = (readin(1ll) + las) % w;
        D <<= 1;
        int u = e[D].to;
        if(dep[u] < dep[e[D ^ 1].to])
            u = e[D ^ 1].to;
        // printf("update u == %d\n", u);
        ll delta = E - e[D].w;
        e[D].w = e[D ^ 1].w = E;
        // printf("delta == %lld\n", delta);
        bit.modify(dfn[u], dfn[u] + sz[u] - 1, delta);
        Modify(dfn[u], dfn[u] + sz[u] - 1);
        writc(las = tre[1].d, '\n');
        // rep(i, 1, n) printf("dis %d == %lld\n", i, bit.query(dfn[i]));
        // print();
    }
    return 0;
}
posted @ 2021-01-05 19:07  Arextre  阅读(102)  评论(0编辑  收藏  举报