P6845

考虑按 DFS 序建线段树,每个节点维护区间直径。

那么如果修改的边是 \((x,y)\),其中 \(x\)\(y\) 的父亲,设 \(y\) 子树内 DFS 序最小值和最大值分别为 \(l,r\),那么影响到的线段树节点就是所有和 \([l,r]\) 有交且不被 \([l,r]\) 包含的区间。

由线段树的性质可知这样的区间只有 \(O(\log n)\) 个,暴力重新计算这些区间的信息即可。

由于 pushup 的时候需要查询链上和,所以复杂度是 \(O(n\log^2n)\)。有点不爽的

#include<bits/stdc++.h>

#define int long long

using namespace std;

inline int read(){
	int x=0,f=1;char c=getchar();
	for(;(c<'0'||c>'9');c=getchar()){if(c=='-')f=-1;}
	for(;(c>='0'&&c<='9');c=getchar())x=x*10+(c&15);
	return x*f;
}

const int MN=1e5+5;

int n,q,w;
int fr[MN],to[MN],val[MN];

struct BIT{
	int c[MN];
	int lowbit(int x){return x&(-x);}
	void add(int x,int k){for(int i=x;i<=n;i+=lowbit(i))c[i]+=k;}
	int sum(int x){int res=0;for(int i=x;i;i-=lowbit(i))res+=c[i];return res;}
}T;

struct Edge{
	int to,cost;
	Edge(int T,int C):to(T),cost(C){}
	Edge(){}
};

vector<Edge>G[MN];

namespace HLD{
	int dep[MN],dfn[MN],sz[MN],hson[MN],top[MN],fa[MN];
	int dis[MN],rk[MN];

	void dfs1(int u,int de){
		dep[u]=de,sz[u]=1;
		for(auto e:G[u]){
			int v=e.to,w=e.cost;
			if(v==fa[u])continue;
			dis[v]=dis[u]+w,fa[v]=u,dfs1(v,de+1),sz[u]+=sz[v];
			if(sz[v]>sz[hson[u]])hson[u]=v;
		}
	}

	int tot=0;
	void dfs2(int u,int tp){
		top[u]=tp,dfn[u]=++tot,rk[dfn[u]]=u;
		if(hson[u])dfs2(hson[u],tp);
		for(auto e:G[u]){
			int v=e.to,w=e.cost;
			if(v==fa[u]||v==hson[u])continue;
			dfs2(v,v);
		}
	}

	int LCA(int x,int y){
		while(top[x]!=top[y]){
			if(dep[top[x]]<dep[top[y]])swap(x,y);
			x=fa[top[x]];
		}
		if(dep[x]>dep[y])swap(x,y);
		return x;
	}

	int getdis(int x){return T.sum(dfn[x]);}

	int dist(int x,int y){
		int z=LCA(x,y);
		return getdis(x)+getdis(y)-getdis(z)*2;
	}

	void build(){
		for(int i=1;i<=n;i++)T.add(i,dis[rk[i]]-dis[rk[i-1]]);
	}

	void add(int x,int k){
		int l=dfn[x],r=dfn[x]+sz[x]-1;
		T.add(l,k),T.add(r+1,-k);
	}
};

struct Node{
	int u,v;
	Node(int U,int V):u(U),v(V){}
	Node(){}
};

#define ls(p) (p<<1)
#define rs(p) (p<<1|1)

struct SegTree{
	Node d[MN<<2];

	inline void build(int l,int r,int p){
		if(l==r){
			d[p].u=d[p].v=HLD::rk[l];
			return ;
		}
		int mid=(l+r)>>1;
		build(l,mid,ls(p)),build(mid+1,r,rs(p));
		pushup(p);
	}

	inline void pushup(int p){
		int x=d[ls(p)].u,y=d[ls(p)].v;
		int a=d[rs(p)].u,b=d[rs(p)].v;
		int mx=HLD::dist(x,y),ax=x,ay=y;
		int t=HLD::dist(x,a);if(t>mx)mx=t,ax=x,ay=a;
		t=HLD::dist(x,b);if(t>mx)mx=t,ax=x,ay=b;
		t=HLD::dist(y,a);if(t>mx)mx=t,ax=y,ay=a;
		t=HLD::dist(y,b);if(t>mx)mx=t,ax=y,ay=b;
		t=HLD::dist(a,b);if(t>mx)mx=t,ax=a,ay=b;
		d[p].u=ax,d[p].v=ay;
	}

	inline void modify(int l,int r,int ql,int qr,int p){
		if(l<=ql&&qr<=r)return ;
		int mid=(ql+qr)>>1;
		if(l<=mid)modify(l,r,ql,mid,ls(p));
		if(r>mid)modify(l,r,mid+1,qr,rs(p));
		pushup(p);
	}

	inline int get(){
		return HLD::dist(d[1].u,d[1].v);
	}
}Tree;

signed main(void){

#ifndef ONLINE_JUDGE
	freopen("in.in","r",stdin);
#endif

	n=read(),q=read(),w=read();
	for(int i=1;i<=n-1;i++){
		int u=read(),v=read(),w=read();
		G[u].push_back(Edge(v,w)),G[v].push_back(Edge(u,w));
		fr[i]=u,to[i]=v,val[i]=w;
	}

	HLD::dfs1(1,1),HLD::dfs2(1,1),HLD::build();int lans=0;
	Tree.build(1,n,1);

	// cout<<HLD::getdis(1)<<" "<<HLD::getdis(2)<<" "<<HLD::getdis(3)<<" "<<HLD::getdis(4)<<endl;
	// cout<<Tree.get()<<endl;

	while(q--){
		int d=(read()+lans)%(n-1)+1,e=(read()+lans)%w;
		int u;
		if(HLD::dep[fr[d]]>HLD::dep[to[d]])u=fr[d];
		else u=to[d];
		HLD::add(u,e-val[d]);val[d]=e;
		Tree.modify(HLD::dfn[u],HLD::dfn[u]+HLD::sz[u]-1,1,n,1);
		cout<<(lans=Tree.get())<<'\n';
	}

	return 0;
}
posted @ 2023-12-20 18:29  云浅知处  阅读(79)  评论(0编辑  收藏  举报