P6845
他是一个带修改的直径,直径就是两点间最长距离,很容易想到用差分,\(dis_x\) 表示 \(x\) 到根节点的距离 \(dis_x + dis_y - 2dis_{lca(x,y)}\) 去求,先抛开这个 \(lca\) , 修改一条边相当于修改这个边所对应的子树,显然可以用线段树去做,搞一个 \(dfs\) 序,改的话就用加标记,维护 \(mx,ans\) , \(ans_x = max(ans_{ls},ans_{rs},mx_{ls}+mx_{rs})\) 全部这其中难办的点就是这个 \(lca\) ,想到可以用欧拉序来求,我们会发现两点 \(lca\) 在两点所夹的区间中,且是这个区间里的 \(dis_{min}\),可是单个 \(lca\) 比较难求,我们可以做一步转化,将点转到序列上,在这个区间中正确的 \(lca\) 所产生的就一定是这个区间里贡献最大的,所以即使考虑其他区间中的点也对答案没有影响,所以转化为了:
- 区间修改
- 给你 \(a,c\) ,对于 \(b\), \(a \le b \le c\) ,求 \(s_a + s_c - 2s_b\) 最大值
由于这三个数是有位置限制,那么合并的时候有位置限制的两个数就可以前面的从 \(ls\) 转移,后面的从 \(rs\) 转移,所以可以考虑维护 \(mx,mn,ab,bc,abc,lzy\) ,如 \(abc_x = max(abc_{ls},abc_{rs},ab_{ls}+mx_{rs},mx_{ls}+ab_{rs})\) ,其他的随便转移即可。
#include <bits/stdc++.h>
#define int long long
#define maxn 100010
#define pb push_back
#define vec vector
#define pii pair<int,int>
#define fir first
#define sec second
#define ls (x << 1)
#define rs (x << 1 | 1)
#define mid ((l + r) >> 1)
using namespace std;
int n,q,w;
vec <pii> v[maxn];
struct edge{int x,y,w;
}e[maxn];
int dfn[maxn << 1];
int l[maxn],r[maxn];
int tot = 0;
int dep[maxn];
int dis[maxn];
struct node{int mx,mn;int ab,bc,abc;int lzy;
}s[maxn << 3];
void dfs(int x,int fa){dfn[++tot] = x;dep[x] = dep[fa] + 1;l[x] = tot;for(auto to : v[x]){int y = to.fir,w = to.sec;if(y == fa){continue;}dis[y] = dis[x] + w;dfs(y,x);dfn[++tot] = x; }r[x] = tot;
}
void up(int x){s[x].mn = min(s[ls].mn,s[rs].mn);s[x].mx = max(s[ls].mx,s[rs].mx);s[x].ab = max(s[ls].mx - s[rs].mn * 2,max(s[ls].ab,s[rs].ab));s[x].bc = max(s[rs].mx - s[ls].mn * 2,max(s[ls].bc,s[rs].bc));s[x].abc = max(max(s[ls].abc,s[rs].abc),max(s[ls].mx + s[rs].bc,s[ls].ab + s[rs].mx));
}
void build(int x,int l,int r){if(l == r){int now = dis[dfn[l]];s[x] = {now,now,-now,-now,0};return ; }build(ls,l,mid);build(rs,mid + 1,r);up(x);
}
void down(int x){s[ls].lzy += s[x].lzy;s[rs].lzy += s[x].lzy;s[ls].mn += s[x].lzy;s[rs].mn += s[x].lzy;s[ls].mx += s[x].lzy;s[rs].mx += s[x].lzy;s[ls].ab -= s[x].lzy;s[rs].ab -= s[x].lzy;s[ls].bc -= s[x].lzy;s[rs].bc -= s[x].lzy;s[x].lzy = 0;
}
void modify(int x,int l,int r,int L,int R,int v){if(L <= l && R >= r){s[x].mx += v;s[x].mn += v;s[x].ab -= v;s[x].bc -= v;s[x].lzy += v;return ;}if(s[x].lzy){down(x);}if(L <= mid){modify(ls,l,mid,L,R,v);}if(R > mid){modify(rs,mid + 1,r,L,R,v);}up(x);
}
signed main(){cin >> n >> q >> w;for(int i = 1,x,y,z;i < n;i++){cin >> x >> y >> z;v[x].pb({y,z});v[y].pb({x,z});e[i] = {x,y,z};}dfs(1,0);build(1,1,tot);int ans = 0;for(int i = 1,x,y;i <= q;i++){cin >> x >> y;x = (x + ans) % (n - 1) + 1;y = (y + ans) % w;int now;if(dep[e[x].x] < dep[e[x].y]){now = e[x].y;}else{now = e[x].x; }modify(1,1,tot,l[now],r[now],y - e[x].w);e[x].w = y;ans = s[1].abc;cout << ans << endl;}
}