P6845 [CEOI 2019] Dynamic Diameter

钦定一个根,考虑用数据结构维护维护节点深度,这是好做的。再用一颗线段树维护直径,对于修改,把跟节点到修改区间上的点全部 \(push\_up\) 一次就可以了。

代码

#include<bits/stdc++.h>
using namespace std;
namespace IO{
    template<typename T>
    inline void read(T&x){
        x=0;char c=getchar();bool f=0;
        while(!isdigit(c)) c=='-'?f=1:0,c=getchar();
        while(isdigit(c)) x=x*10+c-'0',c=getchar();
        f?x=-x:0;
    }
    template<typename T>
    inline void write(T x){
        if(x==0){putchar('0');return ;}
        x<0?x=-x,putchar('-'):0;short st[50],top=0;
        while(x) st[++top]=x%10,x/=10;
        while(top) putchar(st[top--]+'0');
    }
    inline void read(char&c){c=getchar();while(isspace(c)) c=getchar();}
    inline void write(char c){putchar(c);}
    inline void read(string&s){s.clear();char c;read(c);while(!isspace(c)&&~c) s+=c,c=getchar();}
    inline void write(string s){for(int i=0,len=s.size();i<len;i++) putchar(s[i]);}
    template<typename T>inline void write(T*x){while(*x) putchar(*(x++));}
    template<typename T,typename...T2> inline void read(T&x,T2&...y){read(x),read(y...);}
    template<typename T,typename...T2> inline void write(const T x,const T2...y){write(x),putchar(' '),write(y...),sizeof...(y)==1?putchar('\n'):0;}
}using namespace IO;
#define int long long
#define LL long long
const int maxn=100010;
int n,q,dfn[maxn],cnt,dfn_out[maxn],deep[maxn],fan[maxn],fa[maxn];
LL w;
struct EDGE{int u,v;LL w;}b[maxn];
vector<pair<int,LL>>e[maxn];
inline void dfs(int u,int fa=0){
    ::fa[u]=fa;
    deep[u]=deep[fa]+1;
    dfn[u]=++cnt;fan[cnt]=u;
    for(auto i:e[u]){
        int v=i.first;
        if(v==fa) continue;
        dfs(v,u);
    }
    dfn_out[u]=cnt;
}
template<typename T>class ST{
private:
    T st[maxn][20];
    int lg[maxn];
public:
    inline void build(T a[]){
        for(int i=1;i<=n;i++) st[i][0]=a[i],lg[i]=__lg(i);
        lg[0]=1;
        for(int j=1;j<=17;j++) for(int i=1;i<=n;i++){
            int k=i+(1<<j-1);
            if(k>n) k=n;
            st[i][j]=min(st[i][j-1],st[k][j-1]);
        }
    }
    inline T query(int l,int r){
        int lgg=lg[r-l+1];
        return min(st[l][lgg],st[r-(1<<lgg)+1][lgg]);
    }
};
struct node_for_cmp{
    int first,second;
    inline bool operator<(const node_for_cmp t)const{return first<t.first;}
};
node_for_cmp pair_for_build[maxn];
ST<node_for_cmp>st;
inline int lca(int u,int v){
    if(u==v) return u;
    int w=dfn[u],ww=dfn[v];
    if(w>ww) swap(w,ww);
    node_for_cmp l=st.query(w+1,ww);
    return fa[l.second];
}
class BIT_for_Dis{
private:
    int t[maxn];
    int low(int u){return u&-u;}
    void update(int u,int add){while(u<=n) t[u]+=add,u+=low(u);}
    int query(int u){int ans=0;while(u) ans+=t[u],u-=low(u);return ans;}
public:
    inline void update(int l,int r,LL z){update(l,z),update(r+1,-z);}
    inline int operator[](const int wz){return query(wz);}
}d;
inline LL get_dis(int u,int v){
    u=fan[u],v=fan[v];
    int l=lca(u,v);
    return d[dfn[u]]+d[dfn[v]]-d[dfn[l]]*2;
}
class Segment_Tree_for_Diameter{
private:
    struct node{int d1,d2;}t[maxn*8];
    inline node merge(node a,node b){
        int d[]={0,a.d1,a.d2,b.d1,b.d2};
        int maxd1,maxd2;
        LL maxx=0;
        for(int i=1;i<=4;++i) for(int j=1;j<i;++j){
            int d1=d[i],d2=d[j];
            if(!d1||!d2) continue;
            LL new_dis=get_dis(d1,d2);
            if(new_dis>=maxx) maxx=new_dis,maxd1=d1,maxd2=d2;
        }
        return(node){maxd1,maxd2};
    }
    inline void push_up(int u){t[u]=merge(t[u<<1],t[u<<1|1]);}
    inline void update(int u,int l,int r,int ll,int rr){
        if(l>rr||r<ll) return ;
        if(ll<=l&&r<=rr) return ;
        int mid=l+r>>1;
        update(u<<1,l,mid,ll,rr),update(u<<1|1,mid+1,r,ll,rr);
        push_up(u);
    }
public:
    inline void update(int l,int r){update(1,1,n,l,r);}
    inline LL query(){return get_dis(t[1].d1,t[1].d2);}
    inline void build(int u=1,int l=1,int r=n){
        if(l==r){t[u].d1=t[u].d2=l;return ;}
        int mid=l+r>>1;
        build(u<<1,l,mid);build(u<<1|1,mid+1,r);
        push_up(u);
    }
}t;
signed main(){
    read(n,q,w);
    for(int i=1;i<n;i++){
        int u,v;LL w;read(u,v,w);
        b[i]={u,v,w};
        e[u].push_back({v,w}),e[v].push_back({u,w});
    }
    for(int i=1;i<=n;i++) d.update(i,i,0);
    dfs(1);
    for(int i=1;i<=n;i++) pair_for_build[dfn[i]]={deep[i],i};
    st.build(pair_for_build);
    for(int u=1;u<=n;u++) for(auto i:e[u]){
        int v=i.first;
        if(deep[u]<deep[v]) continue;
        d.update(dfn[u],dfn_out[u],i.second);
    }
    t.build();
    LL ltans=0;
    for(int i=1;i<=q;i++){
        int d;
        LL e;read(d,e);
        d=(d+ltans)%(n-1)+1;e=(e+ltans)%w;
        LL add=e-b[d].w;
        b[d].w=e;
        if(deep[b[d].u]>deep[b[d].v]) d=b[d].u;
        else d=b[d].v;
        ::d.update(dfn[d],dfn_out[d],add);
        t.update(dfn[d],dfn_out[d]);
        write(ltans=t.query());write("\n");
    }
    return 0;
}
posted @ 2026-01-12 21:12  Link-Cut_Trees  阅读(7)  评论(0)    收藏  举报