题解:P16826 [AFOI 2025] C.道路修复

· · 题解

钦定 1 是根。

先预处理出每个点子树内外的静态最远和次远点,可以用换根 dp+线段树动态维护区间最大次大值及下标。

一次操作会把以 u 为根 v 的子树缩成一个菊花,且菊花每个点到 v 及菊花外部的点距离不变。路径长度会增加的只有菊花内部的点对,因为路径需要强制经过 v

一个菊花可能是一棵子树或者整棵树去掉一棵子树。再开一棵线段树维护一个编号 id,代表每个点属于哪一个菊花,这是为了查询操作快速地找到 s 属于哪个菊花。

修改操作时将菊花所有的叶子(即不包括根)赋值。每次操作前先进行检查,如果根被赋值过则这次操作是无效的(因为根已经是叶子了),跳过它。

查询操作答案有这么几类:

:::info[代码共 5.5k,去掉缺省源 3.3k。]

#include<bits/stdc++.h>
#define il inline
#define ui unsigned int
#define ll long long
#define ull unsigned ll
#define lll __int128
#define db double
#define ldb long double
#define pii pair<int,int>
#define vi vector<int>
#define vpii vector<pii>
#define fir first
#define sec second
#define gc getchar
#define pc putchar
#define pb push_back
#define lb lower_bound
#define ub upper_bound
#define pct __builtin_popcount
#define mst(a,x) memset(a,x,sizeof a)
#define mcp(a,b) memcpy(a,b,sizeof b)
using namespace std;
const int N=5e5+10,INF=0x3f3f3f3f,MOD=998244353;
const ll INFll=0x3f3f3f3f3f3f3f3f;
il int rd() {int x=0,f=1; char ch=gc(); while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=gc();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc(); return x*f;}
il ll rdll() {ll x=0; int f=1; char ch=gc(); while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=gc();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc(); return x*f;}
il void wr(int x) {if(x==INT_MIN) return printf("-2147483648"),void(); if(x<0) return pc('-'),wr(-x); if(x<10) return pc(x+'0'),void(); wr(x/10),pc(x%10+'0');}
il void wrll(ll x) {if(x==LLONG_MIN) return printf("-9223372036854775808"),void(); if(x<0) return pc('-'),wrll(-x); if(x<10) return pc(x+'0'),void(); wrll(x/10),pc(x%10+'0');}
il void wr(int x,const char *s) {wr(x),printf("%s",s);}
il void wrll(ll x,const char *s) {wrll(x),printf("%s",s);}
il int vmod(int x) {return x>=MOD?x-MOD:x;}
il int vadd(int x,int y) {return vmod(x+y);}
il int vsub(int x,int y) {return vmod(x-y+MOD);}
il int vmul(int x,int y) {return 1ll*x*y%MOD;}
il int qpow(int x,int y) {int r=1; for(;y;y>>=1,x=vmul(x,x)) if(y&1) r=vmul(r,x); return r;}
il void cadd(int &x,int y) {x=vmod(x+y);}
il void csub(int &x,int y) {x=vmod(x-y+MOD);}
il void cmul(int &x,int y) {x=vmul(x,y);}
il void cmax(int &x,int y) {x<y&&(x=y);}
il void cmaxll(ll &x,ll y) {x<y&&(x=y);}
il void cmin(int &x,int y) {x>y&&(x=y);}
il void cminll(ll &x,ll y) {x>y&&(x=y);}
int n,id,hd[N],ac[N][20],d[N],L[N],R[N],rk[N],w[N];
ll ds[N];
struct EDGE {int to,w,ne;} e[N*2];
int idx;
il void add(int u,int v,int w) {e[++id]={v,w,hd[u]},hd[u]=id;}
void dfs(int u,int fa) {
    ac[u][0]=fa,d[u]=d[fa]+1,L[u]=++idx,rk[idx]=u;
    for(int i=1;i<20;i++) ac[u][i]=ac[ac[u][i-1]][i-1];
    for(int i=hd[u],v;i;i=e[i].ne) if((v=e[i].to)!=fa)
        ds[v]=ds[u]+e[i].w,w[v]=e[i].w,dfs(v,u);
    R[u]=idx;
}
int jp(int u,int k) {
    for(int i=19;~i;i--) if(k>>i&1) u=ac[u][i];
    return u;
}
int lca(int u,int v) {
    if(d[u]<d[v]) swap(u,v);
    for(int i=19;~i;i--) if(d[ac[u][i]]>=d[v]) u=ac[u][i];
    if(u==v) return u;
    for(int i=19;~i;i--) if(ac[u][i]!=ac[v][i]) u=ac[u][i],v=ac[v][i];
    return ac[u][0];
}
#define pli pair<ll,int>
#define pll pair<pli,pli>
pll mg(pll a,pll b) {
    pll rs;
    if(a.fir>b.fir) rs.fir=a.fir,rs.sec=max(a.sec,b.fir);
    else rs.fir=b.fir,rs.sec=max(a.fir,b.sec);
    return rs;
}
struct SGT {
#define ls (id<<1)
#define rs (id<<1|1)
#define mid (l+r>>1)
#define all 1,1,n
#define Ls ls,l,mid
#define Rs rs,mid+1,r
    pll tr[N*4];
    ll tg[N*4];
    il void ad(int id,ll k) {
        tr[id].fir.fir+=k;
        if(tr[id].sec.sec) tr[id].sec.fir+=k;
        tg[id]+=k;
    }
    il void pd(int id) {ad(ls,tg[id]),ad(rs,tg[id]),tg[id]=0;}
    void bld(int id,int l,int r) {
        if(l==r) return tr[id]={{ds[rk[l]],rk[l]},{0,0}},void();
        bld(Ls),bld(Rs),tr[id]=mg(tr[ls],tr[rs]);
    }
    void upd(int id,int l,int r,int L,int R,int k) {
        if(L>R) return; if(L<=l&&r<=R) return ad(id,k);
        pd(id),L<=mid?upd(Ls,L,R,k):void(),R>mid?upd(Rs,L,R,k):void(),tr[id]=mg(tr[ls],tr[rs]);
    }
    pll qry(int id,int l,int r,int L,int R) {
        if(L>R) return {{0,0},{0,0}}; if(L<=l&&r<=R) return tr[id];
        pd(id);
        if(L<=mid&&R>mid) return mg(qry(Ls,L,R),qry(Rs,L,R));
        if(L<=mid) return qry(Ls,L,R);
        return qry(Rs,L,R);
    }
} sgt;
pll f[N],g[N];
void dfs2(int u,int fa,int fr) {
    f[u]=mg(sgt.qry(all,1,L[u]-1),sgt.qry(all,R[u]+1,n));
    g[u]=sgt.qry(all,L[u],R[u]);
    for(int i=hd[u],v;i;i=e[i].ne) if((v=e[i].to)!=fa) {
        sgt.upd(all,1,L[v]-1,e[i].w),sgt.upd(all,L[v],R[v],-e[i].w),sgt.upd(all,R[v]+1,n,e[i].w);
        dfs2(v,u,e[i].w);
        sgt.upd(all,1,L[v]-1,-e[i].w),sgt.upd(all,L[v],R[v],e[i].w),sgt.upd(all,R[v]+1,n,-e[i].w);
    }
}
struct S2 {
    int vl[N*4],tg[N*4];
    il void ad(int id,int k) {vl[id]=tg[id]=k;}
    il void pd(int id) {if(tg[id]) ad(ls,tg[id]),ad(rs,tg[id]),tg[id]=0;}
    void upd(int id,int l,int r,int L,int R,int k) {
        if(L>R) return; if(L<=l&&r<=R) return ad(id,k);
        pd(id),L<=mid?upd(Ls,L,R,k):void(),R>mid?upd(Rs,L,R,k):void();
    }
    int qry(int id,int l,int r,int x) {
        if(l==r) return vl[id];
        pd(id); return x<=mid?qry(Ls,x):qry(Rs,x);
    }
} sgt2;
void QwQ() {
    n=rd();
    for(int i=1,u,v,w;i<n;i++) u=rd(),v=rd(),w=rd(),add(u,v,w),add(v,u,w);
    dfs(1,0),sgt.bld(all),dfs2(1,0,0);
    int m=rd();
    for(int o,x,y;m--;) {
        o=rd(),x=rd();
        if(o==1) {
            y=rd();
            if(L[y]<=L[x]&&R[x]<=R[y]) {
                int z=jp(x,d[x]-d[y]-1),c=sgt2.qry(all,L[y]);
                if(!c) sgt2.upd(all,1,L[y]-1,-z),sgt2.upd(all,L[y]+1,L[z]-1,-z),sgt2.upd(all,R[z]+1,n,-z);
            } else {
                int c=sgt2.qry(all,L[y]);
                if(!c) sgt2.upd(all,L[y]+1,R[y],y);
            }
        } else {
            ll as=max(f[x].fir.fir,g[x].fir.fir);
            int c=sgt2.qry(all,L[x]);
            if(c) {
                if(c>0) {
                    if(g[c].fir.sec==x) cmaxll(as,g[c].fir.fir+g[c].sec.fir);
                    else cmaxll(as,ds[x]+ds[c]-ds[lca(x,c)]*2+g[c].fir.fir);
                } else {
                    c=-c;
                    if(f[c].fir.sec==x) cmaxll(as,f[c].fir.fir+f[c].sec.fir-w[c]*(!!f[c].fir.sec+!!f[c].sec.sec));
                    else cmaxll(as,ds[x]+ds[c]-ds[lca(x,c)]*2+f[c].fir.fir-w[c]*(1+!!f[c].fir.sec));
                }
            }
            wrll(as,"\n");
        }
//      for(int i=1;i<=n;i++) wr(sgt2.qry(all,i)," "); puts("");
    }
}
signed main() {
//  freopen("in.in","r",stdin),freopen("out.out","w",stdout);
    int T=1; while(T--) QwQ();
}