P6845 [CEOI 2019] Dynamic Diameter

P6845 [CEOI 2019] Dynamic Diameter

题目描述

有一棵树,含 \(n\) 个节点,边带权。

会有 \(q\) 次修改,每次会将树上的一条边的边权进行修改,在每次修改后,您需要求出每次修改后,这棵树的直径上的边权和。

本题强制在线。

输入格式

第一行为三个整数 \(n,q,w\),分别表示点的个数,询问的个数和边权的上限。

接下来 \(n-1\) 行,每一行为三个整数 \(a_i,b_i,c_i\),表示 \(a_i\)\(b_i\) 有一条边权为 \(c_i\) 的边。

接下来 \(q\) 行,每行两个经过加密的整数 \(d_j,e_j\)

解密方式如下:

  • \(d_j'=(d_j+\text{last})\bmod(n-1)\)
  • \(e_j'=(e_j+\text{last})\bmod w\)

其中 \(\text{last}\) 表示上一个询问的答案,初值为 \(0\)

表示将第 \(d_j'+1\) 条边的边权改为 \(e_j'\)

输出格式

共输出 \(q\) 行,一行一个整数,第 \(i\) 行的整数表示在第 \(i\) 次修改后的直径上的权值总和。

数据范围

对于 \(100\%\) 的数据,保证 \(2\le n\le 10^5\)\(1\le q\le 10^5\)\(1\le w\le 2\times 10^{13}\)\(1\le a_i,b_i\le n\)\(0\le c_i,e_j<w\)\(0\le d_j<n-1\)

说明

本题译自 Central-European Olympiad in Informatics 2019 Day 1 T2 Dynamic Diameter

Solution:

感觉有点神的树上差分题,首先主播不会 ddp 也不想用 ddp。

首先我们知道 $ dis_{(x,y)} = dep_x + dep_y-2\times dep_{lca(x,y)} $

然后如果我们将树拍出一个 欧拉序 的话我们会发现:在欧拉序上的任意一个以 \(x \ ,\ y\) 为两端点的区间内, \(lca(x,y)\) 一定是其中深度最小的那个。

有了这个性质我们就能很好地维护树的直径了,我们用一颗线段树维护以下值:

\[\left\{ \begin{array}{ll} mx =\ \max\limits_{i\in [l,r]} \ dep_i \\ mi =\ \min\limits_{i\in [l,r]} \ dep_i \\ lp =\ \max\limits_{i\in [l,r]\ ,\ j\in[i,r]} \ dep_i-2\times dep_j \\ rp =\ \max\limits_{i\in [l,r]\ ,\ j\in[l,i]} \ dep_i-2\times dep_j \\ \end{array} \right. \]

然后是转移方程:

\[\left\{ \begin{array}{ll} lp_x =\ \max \ (lp_{ls}\ ,\ lp_{rs}\ ,\ mx_{ls}-2 \times mi_{rs}) \\ rp_x =\ \max \ (rp_{ls}\ ,\ rp_{rs}\ ,\ mx_{rs}-2 \times mi_{ls}) \\ ans = \max (ans_{ls}\ ,\ ans_{rs}\ ,\ lp_{ls}+mx_{rs}\ ,\ rp_{rs}+mx_{ls}) \end{array} \right. \]

然后我们会发现:\(lp,rp\) 式子中的 \(j\) 实际上就是 \(lca\) 可能的位置。那么我们在合并两个区间 \({ls,rs}\) 时,如果当前区间新答案的 lca 落在 \(ls\) 内,那么它会在 \(lp_{ls}\ + \ mx_{rs}\) 中取到,反之则会在 \(rp_{ls}\ +\ mx_{ls}\) 中取到。

然后注意一下,本题我们取的序列是 欧拉序 而非 dfs序 应为上述性质只在 欧拉序 上生效。

Code:

#include<bits/stdc++.h>
#define int long long
const int N=2e5+5;
using namespace std;
int n,m,cnt,W;
vector<tuple<int,int>> E[N];
int q[N],st[N],ed[N],u[N],v[N],w[N],dis[N];
void dfs(int x,int fa)
{
    q[st[x]=++cnt]=x;
    for(auto [to,id] : E[x])
    {
        if(to==fa)continue;
        u[id]=x;
        v[id]=to;
        dis[to]=dis[x]+w[id];
        dfs(to,x);
        q[++cnt]=x;
    }
    ed[x]=cnt;
}
//Segment_Tree
#define ls x<<1
#define rs x<<1|1
struct Tree
{
    int ans,mx,mi,lp,rp,tag;
    inline void push(int val)
    {
        mx+=val;
        mi+=val;
        lp-=val;
        rp-=val;
        tag+=val;
    }
}t[N<<2];
inline void push_up(int x)
{
    t[x].mx=max(t[ls].mx,t[rs].mx);
    t[x].mi=min(t[ls].mi,t[rs].mi);
    t[x].lp=max(max(t[ls].lp,t[rs].lp),t[ls].mx-2*t[rs].mi);
    t[x].rp=max(max(t[ls].rp,t[rs].rp),t[rs].mx-2*t[ls].mi);
    t[x].ans=max(max(t[ls].ans,t[rs].ans),max(t[ls].lp+t[rs].mx,t[ls].mx+t[rs].rp));
    return;
}
inline void push_down(int x)
{
    if(!t[x].tag)return;
    int tag=t[x].tag;t[x].tag=0;
    t[ls].push(tag);t[rs].push(tag);
    return;
}
void build(int x,int l,int r)
{
    if(l==r)
    {
        t[x].mi=t[x].mx= dis[q[l]];
        t[x].lp=t[x].rp=-dis[q[l]];
        t[x].ans=0;
        return;
    }
    int mid = l+r>>1;
    build(ls,l,mid);build(rs,mid+1,r);
    push_up(x);
}
void upd(int x,int l,int r,int L,int R,int val)
{
    if(L<=l&&r<=R)
    {
        t[x].push(val);
        return;
    }
    int mid=l+r>>1;
    push_down(x);
    if(L<=mid) upd(ls,l,mid,L,R,val);
    if(mid<R)upd(rs,mid+1,r,L,R,val);
    push_up(x);
}
void work()
{
    cin>>n>>m>>W;
    cnt=0;
    for(int i=1,x,y,z;i<n;i++)
    {
        scanf("%lld%lld%lld",&x,&y,&z);
        E[x].emplace_back(y,i);
        E[y].emplace_back(x,i);
        w[i]=z;
    }
    dfs(1,0);
    int inf=n*2-1;
    build(1,1,inf);
    int ans=0;
    for(int i=1,id,val;i<=m;i++)
    {
        scanf("%lld%lld",&id,&val);
        id=(id+ans)%(n-1)+1;
        val=(val+ans)%W;
        upd(1,1,inf,st[v[id]],ed[v[id]],val-w[id]);
        ans=t[1].ans;
        w[id]=val;
        printf("%lld\n",ans);
    }
}
#undef int
int main()
{
    //freopen("Dynamic Diameter.in","r",stdin);
    //freopen("Dynamic Diameter.out","w",stdout);
    work();
    return 0;
}
posted @ 2025-04-10 13:09  liuboom  阅读(34)  评论(0)    收藏  举报